Connect your Nintendo Switch playing status to Discord!

Overview

Disclaimer: Unfortunately, it appears that Nintendo has removed returning self-Presence in their API as of recently, making this project near obsolete. This is best addressed in issue #13, but to summarize: This project will have to undergo major changes (possibly unsavory ones) in order to properly receive the necessary information for a Discord status (namely using a friend account).
I'm incredibly sorry for the inconvenience.

Nintendo Switch Online Rich Presence

Display your Nintendo Switch game status on Discord!

This README will be split into two sections:

Credits

This project uses the Nintendo Switch Online Mobile App API.
I'd like to thank:

Quickstart Guide

Download the app from the latest release and run!
Once ran, the app will ask for you to log into your Nintendo account on a web browser. There is no malicious code with intent to steal your information, but it's best to review the code for yourself.

  1. Open Discord first, then NSO-RPC

  2. Log in to your Nintendo account when prompted

  3. Right click on 'Select this account' and press 'Copy Link'

link

  1. Paste the link in the pop-up's form and click 'Log In'

  2. Control your rich presence from the system tray icon

display

FAQ

Q: Do you need a Nintendo Switch Online subscription to use this app?
A: No, you do not. This app works whether or not you have access to online services. You will, however, need to link your Nintendo account to your user profile on your Switch.

Q: My computer says that this app might have a virus! Does it?
A: No. Your computer is saying that because it's a foreign executable file downloaded from the internet, so you should always be cautious about it. If you'd like, you can build your own exe.

Q: You're not stealing my account/data, are you?
A: Not me, personally. You'll have to ask frozenpandaman (s2s) and @NexusMine (flapg). They are responsible for some of the authentication steps. Read more here, and be weary of any possible theft.

  • What if I don't want to use s2s and flapg?

    A: It is possible to tweak the code and remove the API calls, then instead only use temporary tokens you have provided for authorization headers. However, this is tedious and completely up to the user to perform- as the tokens expire after 7200 seconds (two hours) and are only obtainable through methods such as mitmproxy

Q: Do I need Discord open on my PC to use this application?
A: Yes, Discord needs to be open for this application to even run in the first place.

Q: I can't get the program to run, what's wrong with it?!
A: Delete the NSO-RPC folder in your Documents folder. If that doesn't work, you should run the cli.py program and get the error data, then make an issue on Github and I'll investigate it.

Q: I can't link my Nintendo Account. What do I do?
A: Refer to the question above.

I am not liable for any sort of rate limiting Nintendo may hammer upon your network

In-depth guide

Building

For Windows, run

cd .\NSO-RPC\scripts
.\build.bat

For MacOS, run

cd ./NSO-RPC/scripts
chmod +x build.sh
./build.sh

For Linux (Ubuntu), run

cd ./NSO-RPC/scripts
chmod +x install.sh
./install.sh

*(Make sure you have python3 and pip installed)

Understanding

This is going to be a detailed explanation on everything that I do here and exactly what is going on. If you're into that sort of stuff, keep reading. If not, feel free to skim and get a general idea of the procedures.
I try my best to be detailed and give a proper comprehensive guide, but I'm not perfect. Feel free to make an issue if you feel anything in particular should be updated!

I'm going to be explaining my cli.py as it isn't as complicated as the GUI (app.py).
(You can follow along with the guide here and here)

1. Getting your session_token

First things first, we need to get access to your Nintendo account. What we need to get is your session_token, which is a unique identifier that confirms to Nintendo servers you are you. This is the code that gets your session_token.
cli.py:

path = os.path.expanduser('~/Documents/NSO-RPC/private.txt')
  if not os.path.isfile(path):
      session = Session()
      session_token = session.run(*session.login(session.inputManually))
  else:
      with open(path, 'r') as file:
          session_token = json.loads(file.read())['session_token']

First, it checks if you already have a session_token saved. If so, then it just uses that.
If not, then it will create a Session() object and call Session().login() (passing Session().inputManually) Session().run().
That's all fine and dandy, but what does it do behind the Session().login() and Session.run() functions?
Glad you asked.

  • Session().__init__():

    First, it sets some default headers and creates a requests.Session() (this is from the common Python library, requests).

    self.headers = {
      'Accept-Encoding': 'gzip',
      'User-Agent': 'OnlineLounge/%s NASDKAPI Android' % nsoAppVersion,
    }
    self.Session = requests.Session()
  • Session().login():

    Now, we create some variables (as dictated from s2s) for authorization. Basically just a bunch of random characters, but your guess is honestly as good as mine when it comes down to it, as I'm not an expert on oauth authentication.

    state = base64.urlsafe_b64encode(os.urandom(36))
    verify = base64.urlsafe_b64encode(os.urandom(32))
    authHash = hashlib.sha256()
    authHash.update(verify.replace(b'=', b''))
    authCodeChallenge = base64.urlsafe_b64encode(authHash.digest())

    Here, it sets up authentication form, queries it, gets the URL, and opens it in the user's web browser.

    url = 'https://accounts.nintendo.com/connect/1.0.0/authorize'
    params = {
      'client_id': client_id,
      'redirect_uri': 'npf%s://auth' % client_id,
      'response_type': 'session_token_code',
      'scope': 'openid user user.birthday user.mii user.screenName',
      'session_token_code_challenge': authCodeChallenge.replace(b'=', b''),
      'session_token_code_challenge_method': 'S256',
      'state': state,
      'theme': 'login_form'
    }
    response = self.Session.get(url, headers = self.headers, params = params)
    
    webbrowser.open(response.history[0].url)

    Finally, it comes to the user's input. We re.compile() the proper format of a return token (thank you, blackgear). Then, using the input method specified in Session().login(), we receive the user's URL and re.findall() for the proper code.
    We'll then return the code and verify variables.

    tokenPattern = re.compile(r'(eyJhbGciOiJIUzI1NiJ9\.[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*)')
    code = tokenPattern.findall(receiveInput())[0]
    
    return code, verify
  • Session().inputManually():

    Session().inputManually() is literally just a redirect of the Python input() function:

    def inputManually(self):
      return input('After logging in, please copy the link from \'Select this account\' and enter it here:\n')
  • Session().run():

    Session().run() returns the session_token in a finally usable format:

    url = 'https://accounts.nintendo.com/connect/1.0.0/api/session_token'
    headers = self.headers
    headers.update({
      'Accept-Language': 'en-US',
      'Accept':          'application/json',
      'Content-Type':    'application/x-www-form-urlencoded',
      'Content-Length':  '540',
      'Host':            'accounts.nintendo.com',
      'Connection':      'Keep-Alive',
    })
    body = {
      'client_id': client_id,
      'session_token_code': code,
      'session_token_code_verifier': verify.replace(b'=', b''),
    }
    response = self.Session.post(url, data = body, headers = headers)
    return json.loads(response.text)['session_token']

2. Connecting to Discord

We create a Discord() object and pass the newly obtained session_token (and user_lang) to it. This does not involve sending your session_token to Discord.
cli.py:

client = Discord(session_token, user_lang)
client.background()
  • Discord().__init__():

    First, it creates a pypresence.Presence() object and passes it my Discord Application ID (this has nothing important other than the name 'Nintendo Switch'; you can replace it with your own ID if you want)
    Then, it calls Discord().connect() to connect to the Discord client.
    We set the Discord().running and Discord().gui variables to False, then if the parameters session_token and user_lang are passed, it will call Discord().createCTX().

    self.rpc = None
    if rpc:
        if not self.connect():
            sys.exit()
    self.running = False
    self.api = None
    self.gui = False
    if session_token and user_lang:
        self.createCTX(session_token, user_lang)
  • Discord().createCTX():

    This function just creates an API() object and sets it to Discord().api. It also sets Discord().running to True.
    It requires a session_token and a user_lang to be passed.

    try:
      self.api = API(session_token, user_lang)
    except Exception as e:
      sys.exit(log(e))
    self.running = True
  • Discord().connect():

    If this errors over 500 times, the application closes.

    self.rpc = pypresence.Presence('637692124539650048')
    fails = 0
    while True:
      # Attempt to connect to Discord. Will wait until it connects
      try:
        self.rpc.connect()
        break
      except Exception as e:
        fails += 1
        if fails > 500:
          sys.exit(log('Error, failed after 500 attempts\n\'%s\'' % e))
        continue
    • Discord().disconnect():

      Closes rich presence connection.

      if self.rpc:
          self.rpc.close()
      self.rpc = None
  • Discord().setApp():

    This is only called by GUI. All it does is set the usable app function and assign Discord().gui to True.

    def setApp(self, function):
        self.app = function
        self.gui = True
  • Discord().update():

    This updates the user's Discord Rich Presence. Will error if an API() object is not defined at Discord().api
    It basically just calls the API to grab the user's info, then if they are not currently offline, it will update the Discord().rpc.
    If it cannot get the user, it will attempt to login.
    If they are offline, then it will clear their status.
    If a Game().sysDescription is available, it will display that as the Discord state instead of hours played.
    If Discord().gui is True, it will run Discord().app()

    for i in range(2):
        try:
            self.api.getSelf()
            break
        except Exception as e:
            log(e)
            if i > 0 or time.time() - self.api.login['time'] < 7170:
                raise Exception('Cannot get session token properly')
            self.api.updateLogin()
            continue
    self.nickname = self.api.userInfo['nickname']
    self.user = self.api.user
    
    presence = self.user.presence
    if presence.game.name: # Please file an issue if this happens to fail
        state = presence.game.sysDescription
        if not state:
            state = 'Played for %s hours or more' % (int(presence.game.totalPlayTime / 60 / 5) * 5)
            if presence.game.totalPlayTime / 60 < 5:
                state = 'Played for a little while'
        self.rpc.update(details = presence.game.name, large_image = presence.game.imageUri, large_text = presence.game.name, state = state)
    else:
        self.rpc.clear()
    # Set GUI
    if self.gui:
        self.app(self.user)
  • Discord().background():

    This is the background task that runs the entire application. What we do here is that we update the user's status once every 30 seconds. And, uh, that's pretty much it. If Discord().running is not True then it will set the next update to be 5 seconds after Discord().running becomes True again (whenever you toggle the Discord option in the taskbar, this is what happens).

    second = 30
    while True:
        if self.running:
            if second == 30:
                try:
                    self.update()
                except Exception as e:
                    sys.exit(log(e))
                second = 0
            second += 1
        else:
            second = 25
        time.sleep(1)
  • Discord().logout():

    Removes the configs in the config folder.

    path = os.path.expanduser('~/Documents/NSO-RPC')
    if os.path.isfile(os.path.join(path, 'private.txt')):
        try:os.remove(os.path.join(path, 'private.txt'))
        except:pass
        try:os.remove(os.path.join(path, 'settings.txt'))
        except:pass
        sys.exit()

3. Nintendo's API

Oh boy.

Alright, this gets complicated, but I'll try and cover it all quickly.
*For code snippets, see api/__init__.py

  • API():

    Has five functions: API().__init__(), API().makeRequest(), API().updateLogin(), API().getSelf(), and API().getFriends().

    • API().__init__():

      This sets some headers to API().headers and assigns Nintendo().getServiceToken() to API().tokenResponse after passing session_token to it.
      Of all of the important things it retrieves, we only use API().tokenResponse['access_token']. We assign that to the 'Authorization' header.

      self.headers['Authorization'] = 'Bearer %s' % self.accessToken # Add authorization token

      We also create a GUID (uuid.uuid4())
      We set the default URL that isn't really used, then we set API().userInfo to UsersMe().get(), which used in API().updateLogin().
      After that, we store the token in plaintext form in your Documents/NSO-RPC folder. This will likely not be changed as other methods are not really more secure.

    • API().makeRequest():

      Makes a request to https://api-lp1.znc.srv.nintendo.net with a route specified.

      def makeRequest(self, route):
        return requests.post(self.url + route, headers = self.headers)
    • API().updateLogin():

      All this does is create/refresh your Login(). It will check a file in your Documents/NSO-RPC folder for an already existing temporary token so as to prevent excessive calling of the s2s API.
      See Login() for more information.

      path = os.path.expanduser('~/Documents/NSO-RPC/tempToken.txt')
      if os.path.isfile(path):
          with open(path, 'rb') as file:
              self.login = pickle.loads(file.read())
              self.headers['Authorization'] = 'Bearer %s' % self.login['login'].account['result'].get('webApiServerCredential').get('accessToken')
              log('Login from file')
      if time.time() - self.login['time'] < 7170:
          return
      login = Login(self.userInfo, self.user_lang, self.accessToken, self.guid)
      login.loginToAccount()
      self.headers['Authorization'] = 'Bearer %s' % login.account['result'].get('webApiServerCredential').get('accessToken') # Add authorization token
      self.login = {
          'login': login,
          'time': time.time(),
      }
      with open(path, 'wb') as file:
          file.write(pickle.dumps(self.login))
    • API().getSelf():

      This makes a request for user data and assigns it to the API().user variable

      route = '/v3/User/ShowSelf'
      
      response = self.makeRequest(route)
      self.user = User(json.loads(response.text)['result'])
    • API().getFriends():

      This makes a FriendList() object and calls FriendList().populateList(), then assigns FriendList().friendList to API().friends

      list = FriendList()
      list.populateList(self)
      self.friends = list.friendList
  • Nintendo():

    This just makes an API call to Nintendo for a token. Read more here

    • Nintendo().__init__():

      Set a bunch of headers and the body of our request. Requires session_token.

    • Nintendo().getServiceToken():

      Actually make the request, and return it in JSON.

  • UsersMe():

    This gets vital information for the Login() class. It's one step before actually logging in.

    • UsersMe().__init__():

      Sets headers and host url. Takes accessToken (different from session_token).

    • UsersMe().get():

      Very original function name, but it just makes the request. It returns necessary information in JSON format, including the user's date of birth, country, and language.

  • Login():

    • Login().__init__():

      Takes userInfo, userLang, accessToken, guid.
      Sets headers, URL, GUID, user's info, accessToken, Flapg() API, and the user's account.

      Please take extreme caution and note of this piece of code.

      self.flapg = Flapg(self.accessToken, self.timestamp, self.guid).get()
    • Login().loginToAccount():

      Pretty neat. /v3 is necessary for the Presence information.

      route = '/v3/Account/Login'
      body = {
        'parameter': {
          'f': self.flapg['f'],
          'naIdToken': self.flapg['p1'],
          'timestamp': self.flapg['p2'],
          'requestId': self.flapg['p3'],
          'naCountry': self.userInfo['country'],
          'naBirthday': self.userInfo['birthday'],
          'language': self.userInfo['language'],
        },
      }
      response = requests.post(self.url + route, headers = self.headers, json = body)
      self.account = json.loads(response.text)
      return self.account
  • Flapg():

    Learn more about this here
    This is where it can get risky. We are sending off the user's accessToken (a temporary token) to not one, but two third-party APIs. This is what I mentioned in the FAQ about being weary to use this program. It is ran by @NexusMine on Twitter.
    It is, however, necessary in order to call the /v3/Account/Login API, as it retrieves an important factor: The f token.
    Take particular notice of the s2s() call.

    • Flapg().__init__():

      Takes id_token, timestamp, guid.

      self.headers = {
        'x-token': id_token,
        'x-time': str(timestamp),
        'x-guid': guid,
        'x-hash': s2s(id_token, timestamp).getHash(),
        'x-ver': '3',
        'x-iid': 'nso',
      }
      
      self.url = 'https://flapg.com'
    • Flapg().get():

      This just connects to the flapg API and returns the result.

      def get(self):
        route = '/ika2/api/login?public'
      
        response = requests.get(self.url + route, headers = self.headers)
        return json.loads(response.text)['result']
  • s2s():

    Learn more about this here

    • s2s().__init__():

      Takes id_token, timestamp.

      log('Login from Flapg/s2s')
      self.headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'NSO-RPC/%s' % version,
      }
      self.body = {
        'naIdToken': id_token,
        'timestamp': timestamp,
      }
      self.url = 'https://elifessler.com'
    • s2s().getHash():

      route = '/s2s/api/gen2'
      response = requests.post(self.url + route, headers = self.headers, data = self.body)
      return json.loads(response.text)['hash']
  • FriendList():

    Creates and stores a list of Friend() objects

    • FriendList().__init__():

      Defines route and assigns empty list

      self.route = '/v3/Friend/List' # Define API route
      
      self.friendList = [] # List of Friend object(s)
    • FriendList().populateList():

      Requires the passing of an API() object.
      Calls API().makeRequest() with FriendList().route, then assigns the results as Friend() objects to FriendList().friendList

      response = API.makeRequest(self.route)
      arr = json.loads(response.text)['result']['friends']
      self.friendList = [ Friend(friend) for friend in arr ]
  • User():

    This creates an easy-to-use object with the user's data sorted and everything! It's purely for ease-of-use for me.

    • User().__init__():

      Assigns variables from the JSON value it accepts as f.
      Calls Presence()

    • User().description():

      Unused.
      Returns a Python string with a quick description of the User() object.

  • Friend():

    An object used in tandem with FriendList(). Imagine a retexture of the User() class, but with the following additions:

    • Friend().isFriend
    • Friend().isFavoriteFriend
    • Friend().isServiceUser
    • Friend().friendCreatedAt
  • Presence():

    Creates a presence state.
    Calls Game()

  • Game():

    Sorts game data into a neat little class.

4. The f token

This hurts me. This is the reason why we have to call third-party APIs in order to 'login' to Nintendo. It essentially just verifies that you are connecting from a real Nintendo Switch Online Mobile app (ineffectively, obviously).
Since what's required to generate it is potentially incriminating, we have to generate it using third-party APIs (namely s2s and flapg).

Comments
  • Problem with building macOS app & metadata

    Problem with building macOS app & metadata

    Tried to build the macOS app using the June 7 development branch. Terminal had a problem on the "Preparing metadata" step as seen below:

    Screenshot 2022-06-07 at 11 58 13 PM

    I also tested this with the ver 1.2 main branch and got the same result. I'm on an M1 MacBook Pro with macOS 12.3.1.

    opened by CapnCocoa 22
  • Failed to execute script 'app' due to unhandled exception: 'result'

    Failed to execute script 'app' due to unhandled exception: 'result'

    image I've had this issue before and when I reinstalled the app, it all worked again. However, if I reinstall it now, nothing happens and it continues to show that error window on startup. I have to add though, how do I actually fully uninstall the program? I always just deleted the .exe file but that's obviously not a full uninstall, as my login data and account is saved and used again when I 'reinstall' it.

    opened by ScherHap 15
  • Can't run MacOS app

    Can't run MacOS app

    I try to run the app, but a box pops up saying "app Error" with the choices to either Open Console or Terminate. I'm not sure how to fix this issue.

    help wanted 
    opened by zeromotion461 13
  • Too many requests being sent to s2s API

    Too many requests being sent to s2s API

    Lower heavy usage of 3rd-party API / d85286d

    Hi @MCMi460, thanks for this recent change.

    However, the logs show that – currently, as I'm typing this – there's 5 users who are constantly sending requests over and over and over, totaling thousands of requests over the past few hours. This behavior has been seen since the user agent has been updated to 0.2. I'm guessing they're actively running the program and something is going wrong. Can you check to make sure the code's not set up to do this? I've had to ban their IPs; other users are getting rate limit messages and unable to use the API.

    opened by frozenpandaman 9
  • Not able to run on MacOS after first time

    Not able to run on MacOS after first time

    I was able to launch the app just fine the first time but now I get this:

    image

    When running cli.py directly I get this:

    > python cli.py 
      File "cli.py", line 134
        def getToken(manual = True, path:str = os.path.expanduser('~/Documents/NSO-RPC/private.txt')):
                                        ^
    SyntaxError: invalid syntax
    

    I'm not a Python developer so let me know if I'm running the command correctly or if you need any other debug information

    opened by ElLucioVpe 8
  • App crashing on start

    App crashing on start

    Traceback (most recent call last): File "cli.py", line 77, in update File "api_init_.py", line 113, in getSelf File "api_init_.py", line 126, in getFriends File "api_init_.py", line 293, in populateList KeyError: 'result'

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last): File "app.py", line 561, in File "app.py", line 151, in selfService File "app.py", line 258, in changeState File "cli.py", line 83, in update File "api_init_.py", line 104, in updateLogin KeyError: 'result'

    opened by OctoFloofy 8
  • Add the option to

    Add the option to "Start in tray" on start up

    This PR simply adds a setting so when you start the program, it will either show the GUI like default, or have it start in the system tray.

    This partly addresses #50, however I'm not sure how to handle auto starting on operating systems other than windows and this could be handled in its own PR, However this makes other solutions easier/cleaner due to not having to worry about a GUI always showing on startup.

    Note: I also changed the naming of the AnimatedToggle's due to the naming being confusing, and the positioning of the code didn't match top to down. As well as small changes to the positioning of the settings options as I discovered the positioning was slightly off due to an oversized box, so I made it more uniform and the same sized box,

    BWdEY0XhKfGHbaXM


    I also included a small commit that fixes dark's system tray text to be more readable, example of before and after is shown below.

    Before: wZ5GoZ1xGaZlDakH After: cweOBSjXfNfuO05W

    opened by HotaruBlaze 7
  • Nintendo Switch Online API does not return Presence data

    Nintendo Switch Online API does not return Presence data

    Effectively a repost of nxapi's issue - /v3/User/ShowSelf (and apparently /v3/Account/Login and /v3/Account/GetToken) are failing to return Presence object data.

    bug help wanted 
    opened by MCMi460 7
  • Launch error

    Launch error

    Hi! I've been using the program on my Mac. It worked at the start pretty smoothly, but it sometimes had issues with launching, so I'd try deleting the NSO-RPC folder and it would work. However, it doesn't work anymore. I've tried deleting and reinstalling it and it still doesn't work. It launches completely fine before I log in, but after I enter the URL to log in, the app closes (I believe it's supposed to relaunch on its own?) but doesn't open up again. I know it usually takes a while, so I waited about 15 minutes for it, but it still never opened. So I tried to open it myself, and it comes up with this error:

    image

    I read the page and tried opening it with Terminal, but the same issue occurred.

    opened by RepressedNerd 6
  • Add API.refreshAccessToken() for use in API.updateLogin()

    Add API.refreshAccessToken() for use in API.updateLogin()

    What? Token failing to refresh at two hour mark Why? https://github.com/MCMi460/NSO-RPC/issues/21#issuecomment-1159227333 Fix? Generate new token before logging in again Note: It sounds like more work should be done around access_token vs. id_token, and request_id, per @samuelthomas2774 on #21 to keep things kosher, but this is working for me...


    Edit: So far so good running built executable. No crashes/still logged-in, clicking through the app menus hours later (#12) works fine, etc.

    TotalHours        : 24.8919162690278
    
    opened by anthonybaldwin 6
  • Discord Status doesn't work

    Discord Status doesn't work

    For some reason the Discord Status is never appearing while the program is running. It does show as active in the tray but even while playing it never appeared.

    bug 
    opened by OctoFloofy 6
  • [Request] Start with Windows in tray

    [Request] Start with Windows in tray

    Hey there, I recently found out about this amazing program, been looking for something like this for over a year! It works perfectly fine on my end but I got one small request that may can be added in the future.

    Add an option to start the program with windows and hide it in the tray, so you don't have to run the program everytime when you decide to play on your Switch!

    Greetings

    opened by Dekirai 3
  • Demon Throttle

    Demon Throttle

    The latest update seems to have helped a lot with the errors I was getting, but for some reason it shows I am offline when playing Demon Throttle, while all other games appear to work fine.

    opened by QuandoSera 1
  • Discord toggle doesn't want to move, Discord status never changes

    Discord toggle doesn't want to move, Discord status never changes

    Win11 user. I can log in as my own friend and select my main account, and it properly shows my status in program, but never in Discord.

    When I start the program if I go into Settings the Discord toggle is set to off, and clicking it does nothing. It's only after using the Dark Mode toggle that the Discord one will actually change when clicked. Still, having it set to on doesn't actually seem to change anything.

    opened by JoshuaJSlone 1
  • Two hour refresh/login fails

    Two hour refresh/login fails

    I'll dive into more if I have some time, but I'm not making it past the two hour refresh/login (python app.py)... GUI still present and no errors display. Pretty sure same result running just cli.py, but I'd have to test again.

    [Windows 10]

    logs.txt:

    1655351421.3865132: 'result'
    1655351421.3865132: Login from file
    1655351441.3685381: 'result'
    1655351441.3685381: Login from file
    1655351441.3685381: 'result'
    1655351441.3685381: Login from file
    1655351441.3685381: Login from Flapg/s2s
    1655351441.3685381: 'result'
    

    w/ some added prints:

    1655358158.8690448 Checked time at start of update():  7220.071228981018
    1655351441.3685381 log():  'result'
    Attempting to refresh token...
    1655351441.3685381 log():  Login from file
    Time check is:  7220.273142576218
    We didn't pass the 7170 check.
    1655351441.3685381 log():  Login from Flapg/s2s
    s2s response: b'{"hash":"xxx"}'
    Flapg response: b'{"result":{"f":"xxx","p1":"xxx","p2":"xxx","p3":"xxx"}}'
    Before loginToAccount.
    After loginToAccount.
    1655351441.3685381 log():  'result'
    
    opened by anthonybaldwin 4
Releases(v1.3.4)
Owner
Deltaion Lee
I do stuff, known for my sloppy code. Follow me, if you dare.
Deltaion Lee
A cool discord bot, called Fifi

Fifi A cool discord bot, called Fifi This bot is the official server bot of Meme Studios discord server. This github repo is the code we use for the b

Fifi Discord Bot 3 Jun 08, 2021
Bot per controllare la disponibilità di appuntamenti per la vaccinazione Covid-19 in Veneto

VaxBot9000 Prerequisites Python 3.9 Poetry latest version of geckodriver Firefox Setup poetry install Copy config.sample.toml to config.toml and edit

Augusto Zanellato 5 Jun 13, 2021
Modified Version Of Media Search bot

Modified Version Of Media Search bot

1 Oct 09, 2021
Ein PY-Skript, mit dem tiled-Editor-Maps bearbeitet werden

tilesetCopyrighter Ein PY-Skript, mit dem tiled-Editor-Maps bearbeitet werden können fügt je Tileset eine custom-Property tilesetCopyright (string) hi

1 Dec 26, 2021
The best Fortnite all-in-one lobby bot!

Recommended to use on Python v3.8 stable for bot. FLB The best free Fortnite lobby bot experience! Discord server: PDennSploit Softworks LLC Getting S

Payson Holmes 2 May 11, 2022
Scratch2py or S2py is a easy to use, versatile tool to communicate with the Scratch API Based of Scratch2py

Scratch2py Scratch2py or S2py is a easy to use, versatile tool to communicate with the Scratch API Based of Scratch2py Installation Run this command i

2 Jan 13, 2022
How to add reaction on message discord.py

BA / HR / RS: Python (discord.py) skripta pomocu koje dodajete reakciju na vasu poruku putem komande !v ili da se dodaje samo u nekoj odredjenoj sobi.

Seekii 3 Dec 23, 2021
A simple test repo created following docker docs.

docker_sampleRepo A simple test repo created following docker docs. Link to docs: https://docs.docker.com/language/python/develop/ Other links: https:

Suraj Verma 2 Sep 16, 2022
Streaming Finance Data with AWS Lambda

A data pipeline consisting of an AWS lambda function reading data from yfinance API, an AWS Kinesis stream to receive & store data in S3 buckets and AWS Glue crawler & Athena to run SQL queries.

Aarif Munwar Jahan 4 Aug 30, 2022
Sukoshi is a proof-of-concept Python implant that leverages the MQTT protocol for C2 and uses AWS IoT Core as infrastructure.

Sukoshi | 少し Overview Sukoshi is a proof-of-concept Python implant that leverages the MQTT protocol for C2 and uses AWS IoT Core as infrastructure. It

Steven Patterson 37 Oct 29, 2022
A discord webhook client written in Python.

DiscordWebhook A discord webhook client written in Python. Installation pip install webhook-client Example from webhook_client import WebhookClient, E

Elijah 4 Nov 28, 2022
Discord bot that automatically fills out health screenings

Auto Covid Bot Automatically fill out the NYC DOE health screening form by registering with a discord bot School code can be found on https://schoolse

Cleo 2 Jul 29, 2022
A minimalist file manager for those who want to use Linux mobile devices.

Portfolio A minimalist file manager for those who want to use Linux mobile devices. Usage Tap to activate and press to select, to browse, open, copy,

Martin Abente Lahaye 71 Nov 18, 2022
Catware - A powerful grabber with a built in bot control system

catware A powerful grabber with a built in bot control system PLEASE NOTE THAT I

4 Feb 04, 2022
A Telegram Bin Checker Bot made with python for check Bin valid or Invalid. 💳

Bin Checker Bot A Telegram Bin Checker Bot made with python for check Bin valid or Invalid. 📌 Deploy On Heroku 🏷 Environment Variables API_ID - Your

Chamindu Denuwan 20 Dec 10, 2022
WatonAPI is an API used to connect to spigot servers with the WatonPlugin to communicate.

WatonAPI is an API used to connect to spigot servers with the WatonPlugin to communicate. You can send messages to the server and read messages, making it useful for cross-chat programs.

Waton 1 Nov 22, 2021
AWS Glue PySpark - Apache Hudi Quick Start Guide

AWS Glue PySpark - Apache Hudi Quick Start Guide Disclaimer: This is a quick start guide for the Apache Hudi Python Spark connector, running on AWS Gl

Gabriel Amazonas Mesquita 8 Nov 14, 2022
An advanced telegram country information finder bot.

Country-Info-Bot-V2 An advanced telegram country information finder bot Made with Python3 (C) @FayasNoushad Copyright permission under MIT License Lic

Fayas Noushad 16 Nov 12, 2022
A AntiChannelBan Telegram Group Bot Open Source

AntiChannelBan This is a Anti Channel Ban Robots delete and ban message sent by channels Deployment Method Heroku 𝚂𝚄𝙿𝙿𝙾𝚁𝚃 CREDIT BrayDen Blaze

✗ BᵣₐyDₑₙ ✗ 14 May 02, 2022
Token Manager written in Python

Discord-API-Token-Entrance Description This is a Token Manager that allows your token to enter your discord server, written in python. Packages Requir

Tootle 1 Apr 15, 2022