Skip to content

Updated the python script #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions PresenceClient/PresenceClient-Py/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
IP = 'the ip of your device'
APPLICATION_ID = 'your the discord application id'
170 changes: 95 additions & 75 deletions PresenceClient/PresenceClient-Py/presence-client.py
Original file line number Diff line number Diff line change
@@ -1,140 +1,161 @@
import argparse
import sys
import json
import socket
import struct
import time
import re
import requests
import os
from pypresence import Presence
from dotenv import load_dotenv
import subprocess
import time

load_dotenv()

switch_ip = os.getenv('IP')
client_id = os.getenv('APPLICATION_ID')

rpc = Presence(str(client_id))

TCP_PORT = 0xCAFE
PACKETMAGIC = 0xFFAADD23

parser = argparse.ArgumentParser()
parser.add_argument('ip', help='The IP address of your device')
parser.add_argument('client_id', help='The Client ID of your Discord Rich Presence application')
parser.add_argument('--ignore-home-screen', dest='ignore_home_screen', action='store_true', help='Don\'t display the home screen. Defaults to false if missing this flag.')
parser.add_argument('--ignore-home-screen', dest='ignore_home_screen', action='store_true', help='Hide the home screen. Defaults to false if missing this flag.')
parser.add_argument('--ignore-tinfoil', dest='ignore_tinfoil', action='store_true', help='Hide the Tinfoil app. Defaults to false if missing this flag.')
parser.add_argument('--low-latancy', dest='latancy',action='store_true', help='Enable low-latancy mode. Defaults to false if missing this flag.')
parser.set_defaults(ignore_home_screen=False, ignore_tinfoil=False, latancy=False)
consoleargs = parser.parse_args()

questOverrides = None
switchOverrides = None

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
switch_server_address = (switch_ip, TCP_PORT)

if consoleargs.latancy == True:
latancy = 15
else:
latancy = 60

try:
questOverrides = json.loads(requests.get("https://raw.githubusercontent.com/Sun-Research-University/PresenceClient/master/Resource/QuestApplicationOverrides.json").text)
switchOverrides = json.loads(requests.get("https://raw.githubusercontent.com/Sun-Research-University/PresenceClient/master/Resource/SwitchApplicationOverrides.json").text)
except:
print('Failed to retrieve Override files')
exit()

#Defines a title packet
class Title:
def restart():
rpc.clear()
rpc.close()
sock.close()

command = ['python3', 'presence-client.py']

if consoleargs.latancy:
command.append('--low-latancy')
if consoleargs.ignore_tinfoil:
command.append('--ignore-tinfoil')
if consoleargs.ignore_home_screen:
command.append('--ignore-home-screen')

subprocess.Popen(command)
exit()

class Title:
def __init__(self, raw_data):
if len(raw_data) != 628:
restart()

unpacker = struct.Struct('2L612s')
enc_data = unpacker.unpack(raw_data)

self.magic = int(enc_data[0])
if int(enc_data[1]) == 0:
self.pid = int(enc_data[1])
self.name = 'Home Menu'
self.pid = int(enc_data[1])

if self.pid == 0:
self.name = 'Home Menu' if self.magic != PACKETMAGIC else 'Tinfoil'
else:
self.pid = int(enc_data[1])
self.name = enc_data[2].decode('utf-8', 'ignore').split('\x00')[0]
if int(enc_data[0]) == PACKETMAGIC:
if self.name in questOverrides:
if questOverrides[self.name]['CustomName'] != '':
self.name = questOverrides[self.name]['CustomName']
else:
if self.name in switchOverrides:
if switchOverrides[self.name]['CustomName'] != '':
self.name = switchOverrides[self.name]['CustomName']

overrides = questOverrides if self.magic == PACKETMAGIC else switchOverrides
if overrides is not None and self.name in overrides and overrides[self.name]['CustomName']:
self.name = overrides[self.name]['CustomName']

def main():
consoleargs = parser.parse_args()

switch_ip = consoleargs.ip
client_id = consoleargs.client_id

if not checkIP(switch_ip):
print('Invalid IP')
exit()

rpc = Presence(str(client_id))
try:
rpc.connect()
rpc.clear()
except:
print('Unable to start RPC!')

switch_server_address = (switch_ip, TCP_PORT)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
sock.connect(switch_server_address)
print('Successfully connected to %s' % switch_ip + ':' + str(TCP_PORT))
except:
print('Error connection to %s refused' % switch_ip + ':' + str(TCP_PORT))
exit()

while True:
try:
sock.connect(switch_server_address)
print(f'Successfully connected to {switch_ip}:{TCP_PORT}')
break
except socket.error:
print(f'Error connecting to {switch_ip}:{TCP_PORT}. Retrying in {latancy} seconds.')
time.sleep(latancy)
lastProgramName = ''
startTimer = 0

while True:
data = None
try:
sock.settimeout(15)
data = sock.recv(628)
except:
sock.settimeout(None)
except socket.timeout:
sock.settimeout(None)
sock.close()
restart()
except socket.error:
print('Could not connect to Server! Retrying...')
startTimer = 0
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
time.sleep(latancy)
try:
sock.connect(switch_server_address)
print('Successfully reconnected to %s' %
repr(switch_server_address))
except:
print('Error reconnection to %s refused' %
repr(switch_server_address))
exit()
print('Successfully reconnected to %s' % repr(switch_server_address))
except socket.error:
print(f'Error reconnecting to {repr(switch_server_address)}. Retrying...')
time.sleep(latancy)
continue
def get_details(title, overrides):
if title.name in overrides:
orinfo = overrides[title.name]
largeimagekey = orinfo['CustomKey'] or iconFromPid(title.pid)
details = orinfo['CustomPrefix'] or 'Playing'
else:
largeimagekey = iconFromPid(title.pid) if int(title.pid) != PACKETMAGIC else title.name.lower().replace(' ', '')
details = 'Playing'
details += ' ' + title.name
return largeimagekey, details

title = Title(data)
if not hasattr(title, 'magic'):
restart()
continue

if title.magic == PACKETMAGIC:
if lastProgramName != title.name:
startTimer = int(time.time())
if consoleargs.ignore_home_screen and title.name == 'Home Menu':
rpc.clear()
elif consoleargs.ignore_tinfoil and title.name == 'Tinfoil':
rpc.clear()
else:
smallimagetext = ''
largeimagekey = ''
details = ''
largeimagetext = title.name
if int(title.pid) != PACKETMAGIC:
smallimagetext = 'SwitchPresence-Rewritten'
if title.name not in switchOverrides:
largeimagekey = iconFromPid(title.pid)
details = 'Playing ' + str(title.name)
else:
orinfo = switchOverrides[title.name]
largeimagekey = orinfo['CustomKey'] or iconFromPid(title.pid)
details = orinfo['CustomPrefix'] or 'Playing'
details += ' ' + title.name
else:
smallimagetext = 'QuestPresence'
if title.name not in questOverrides:
largeimagekey = title.name.lower().replace(' ', '')
details = 'Playing ' + title.name
else:
orinfo = questOverrides[title.name]
largeimagekey = orinfo['CustomKey'] or title.name.lower().replace(
' ', '')
details = orinfo['CustomPrefix'] or 'Playing'
details += ' ' + title.name
if not title.name:
title.name = ''
lastProgramName = title.name
smallimagetext = 'SwitchPresence-Rewritten' if int(title.pid) != PACKETMAGIC else 'QuestPresence'
overrides = switchOverrides if int(title.pid) != PACKETMAGIC else questOverrides
largeimagekey, details = get_details(title, overrides)
largeimagetext = title.name or ''
lastProgramName = title.name or ''
rpc.update(details=details, start=startTimer, large_image=largeimagekey,
large_text=largeimagetext, small_text=smallimagetext)
time.sleep(1)
else:
time.sleep(1)
rpc.clear()
rpc.close()
sock.close()
Expand All @@ -151,6 +172,5 @@ def checkIP(ip):
def iconFromPid(pid):
return '0' + str(hex(int(pid))).split('0x')[1]


if __name__ == '__main__':
main()