Giter Site home page Giter Site logo

hubspace-py's People

Contributors

jacobklewis avatar jan-leila avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

hubspace-py's Issues

login not working

Hey there,

It appears the location field is missing from the https://accounts.hubspaceconnect.com/auth/realms/thd/login-actions/authenticate?session_code... POST request response headers.

I'm guessing Hubspace (or Keycloak) changed their login flow & this needs to be re-reverse engineered?

Here's what I'm getting (after some basic logging & debugging):

\Python 3.9.2 (default, Mar 12 2021, 04:06:34) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hubspace import Hubspace
>>> h = Hubspace('REDACTED', 'REDACTED')
>>> h.getAccountID()
code_challenge: a9z6xwiMzM669M2KXndaVRvC8LCqCv1H5WtQLh6xgwk
auth url: https://accounts.hubspaceconnect.com/auth/realms/thd/protocol/openid-connect/auth?response_type=code&client_id=hubspace_android&redirect_uri=hubspace-app%3A%2F%2Floginredirect&code_challenge=a9z6xwiMzM669M2KXndaVRvC8LCqCv1H5WtQLh6xgwk&code_challenge_method=S256&scope=openid+offline_access
auth headers: {'User-Agent': 'python-requests/2.27.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
auth response: 200 - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">

<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="robots" content="noindex, nofollow">

    <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css">
    <link rel="icon" href="#" />
            <meta name="viewport" content="width=device-width,initial-scale=1"/>
    <title>Log in to Hubspace</title>
            <link href="/auth/resources/zpbf1/common/keycloak/web_modules/@patternfly/react-core/dist/styles/base.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/web_modules/@patternfly/react-core/dist/styles/app.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/node_modules/patternfly/dist/css/patternfly.min.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/node_modules/patternfly/dist/css/patternfly-additions.min.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/lib/pficon/pficon.css" rel="stylesheet" />

            <link href="/auth/resources/zpbf1/login/hubspace/css/login.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/login/hubspace/css/style.css" rel="stylesheet" />
    <script type="text/javascript">
        function getUrlVars() {
            var vars = [], hash;
            var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

            for(var i = 0; i < hashes.length; i++)
                {
                hash = hashes[i].split('=');
                vars.push(hash[0]);
                vars[hash[0]] = hash[1];
                }

            return vars;
        }
        function togglePassword(id) {
            var passwordField = document.getElementById(id);
            var passwordFieldToggle = document.getElementById('bt-toggle-' + id);
            if(passwordField.getAttribute('type') === 'password') {
                passwordField.setAttribute('type', 'text');
                passwordFieldToggle.value = 'Hide';
            } else {
                passwordField.setAttribute('type', 'password');
                passwordFieldToggle.value = 'Show';
            }
        }

        function clickLocale() {
            var localeDropdown = document.querySelector("#kc-locale ul");
            localeDropdown.style.display = localeDropdown.style.display != "block" ? "block" : "none";
        }


        document.addEventListener("DOMContentLoaded", function(event) {
            var usernameField = document.getElementById('username');
            var usernameInput = getUrlVars()['username'];
            if (usernameInput) {
                usernameField.value = decodeURIComponent(usernameInput);
            }

            var acceptChk = document.getElementById('acceptterms');
            if (acceptChk) {
                acceptChk.onclick = function () {
                    var login = document.getElementById('login-button');
                    console.log('Disabled ' + login.disabled);

                    if(acceptChk.checked) {
                        console.log('enable');
                        login.disabled = false; 
                    } else {
                        console.log('disable');
                        login.disabled = true; 
                    }
                }
            }
        }
   
        
        );
    </script>
</head>

<body class="">
  <div class="login-pf-page">
    <div id="kc-header" class="login-pf-page-header">
      <img src="/auth/resources/zpbf1/login/hubspace/img/hubspace-mobile-logo.png" alt="Hubspace logo" width="628" height="106">
    </div>
    <div class="card-pf ">
      <header class="login-pf-header">

            <div id="kc-locale">
                <div id="kc-locale-wrapper" class="">
                    <div class="kc-dropdown" id="kc-locale-dropdown">
                        <button id="kc-current-locale-link" type="button" onClick="clickLocale()" tabindex=0>
                            English
                        </button>
                        <ul>
                                <li class="kc-dropdown-item"><a href="/auth/realms/thd/login-actions/authenticate?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;kc_locale=en">English</a></li>
                                <li class="kc-dropdown-item"><a href="/auth/realms/thd/login-actions/authenticate?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;kc_locale=fr">Fran�?ais</a></li>
                                <li class="kc-dropdown-item"><a href="/auth/realms/thd/login-actions/authenticate?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;kc_locale=es">Espa�?ol</a></li>
                        </ul>
                    </div>
                </div>
            </div>
                <h1 id="kc-page-title">        Sign In

</h1>
      </header>
      <div id="kc-content">
        <div id="kc-content-wrapper">


    <div id="kc-form" >
      <div id="kc-form-wrapper" >
            <form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="https://accounts.hubspaceconnect.com/auth/realms/thd/login-actions/authenticate?session_code=v9WVbf4WfAEEkUfVEYOzDgYqNJMxAjJVubnT2Fqw_LQ&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;client_id=hubspace_android&amp;tab_id=JwcAo1y86cw" method="post">
                <div class="form-group">
                    <label for="username" class="form-label">Email</label>

                        <input tabindex="0" id="username" class="form-control" name="username" value=""  type="text" inputmode="email" autofocus autocomplete="off" />


                </div>

                <div class="form-group">
                    <label for="password" class="form-label">Password</label>
                    <input tabindex="0" id="password" class="form-control" name="password" type="password" autocomplete="off"/>
                    <input type="button" class="bt-password-toggle" id="bt-toggle-password" onClick="togglePassword('password')"  value='Show'/>
                </div>

                <div class="form-group login-pf-settings">
                    <div id="kc-form-options">
                    
                    </div>
                  
                  </div>

                  <div id="kc-form-buttons" class="form-group">
                      <input type="hidden" id="id-hidden-input" name="credentialId" />
                      <input tabindex="0" class="pf-c-button pf-m-primary btn-block btn-lg" name="login" id="kc-login" type="submit" value="Sign In"/>
                  </div>
                    <div id="kc-form-buttons" class="form-group">
                            <a tabindex="0" href="/auth/realms/thd/login-actions/registration?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw" class="btn reg-button">Register</a>

                    </div>

       
            </form>
        </div>

      </div>



              <div id="kc-info" class="login-pf-signup">
                  <div id="kc-info-wrapper" class="">
                                <span><a tabindex="0" href="/auth/realms/thd/login-actions/reset-credentials?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw">Forgot Password?</a></span>

                  </div>
              </div>
             
        </div>
      </div>

    </div>
  </div>
</body>
</html>
 - {'cache-control': 'no-store, must-revalidate, max-age=0', 'set-cookie': 'AUTH_SESSION_ID=f96ec3fb-2e14-4422-a490-7d4476295aff.keycloak-2; Version=1; Path=/auth/realms/thd/; SameSite=None; Secure; HttpOnly, AUTH_SESSION_ID_LEGACY=f96ec3fb-2e14-4422-a490-7d4476295aff.keycloak-2; Version=1; Path=/auth/realms/thd/; Secure; HttpOnly, KC_RESTART=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2OThhMDY0NS0wZDljLTRlYTktODhiZS0xYzc1OGVjOGIxOGYifQ.eyJjaWQiOiJodWJzcGFjZV9hbmRyb2lkIiwicHR5Ijoib3BlbmlkLWNvbm5lY3QiLCJydXJpIjoiaHVic3BhY2UtYXBwOi8vbG9naW5yZWRpcmVjdCIsImFjdCI6IkFVVEhFTlRJQ0FURSIsIm5vdGVzIjp7InNjb3BlIjoib3BlbmlkIG9mZmxpbmVfYWNjZXNzIiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5odWJzcGFjZWNvbm5lY3QuY29tL2F1dGgvcmVhbG1zL3RoZCIsInJlc3BvbnNlX3R5cGUiOiJjb2RlIiwiY29kZV9jaGFsbGVuZ2VfbWV0aG9kIjoiUzI1NiIsInJlZGlyZWN0X3VyaSI6Imh1YnNwYWNlLWFwcDovL2xvZ2lucmVkaXJlY3QiLCJjb2RlX2NoYWxsZW5nZSI6ImE5ejZ4d2lNek02NjlNMktYbmRhVlJ2QzhMQ3FDdjFINVd0UUxoNnhnd2sifX0.mHeidkIaJqs3hdMeHGxZOcDEAGmxFPQLnXIdCal1o-4; Version=1; Path=/auth/realms/thd/; Secure; HttpOnly', 'x-xss-protection': '1; mode=block', 'x-frame-options': 'SAMEORIGIN', 'referrer-policy': 'no-referrer', 'content-security-policy': "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", 'date': 'Wed, 10 May 2023 03:08:04 GMT', 'x-robots-tag': 'none', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'x-content-type-options': 'nosniff', 'content-type': 'text/html;charset=utf-8', 'content-length': '7719', 'content-language': 'en'}
session url: https://accounts.hubspaceconnect.com/auth/realms/thd/login-actions/authenticate?session_code=v9WVbf4WfAEEkUfVEYOzDgYqNJMxAjJVubnT2Fqw_LQ&execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&client_id=hubspace_android&tab_id=JwcAo1y86cw
session body: username=REDACTED&password=REDACTED&credentialId=
session headers: {'User-Agent': 'python-requests/2.27.1', 'accept-encoding': 'gzip', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': 'AUTH_SESSION_ID=f96ec3fb-2e14-4422-a490-7d4476295aff.keycloak-2; AUTH_SESSION_ID_LEGACY=f96ec3fb-2e14-4422-a490-7d4476295aff.keycloak-2; KC_RESTART=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2OThhMDY0NS0wZDljLTRlYTktODhiZS0xYzc1OGVjOGIxOGYifQ.eyJjaWQiOiJodWJzcGFjZV9hbmRyb2lkIiwicHR5Ijoib3BlbmlkLWNvbm5lY3QiLCJydXJpIjoiaHVic3BhY2UtYXBwOi8vbG9naW5yZWRpcmVjdCIsImFjdCI6IkFVVEhFTlRJQ0FURSIsIm5vdGVzIjp7InNjb3BlIjoib3BlbmlkIG9mZmxpbmVfYWNjZXNzIiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5odWJzcGFjZWNvbm5lY3QuY29tL2F1dGgvcmVhbG1zL3RoZCIsInJlc3BvbnNlX3R5cGUiOiJjb2RlIiwiY29kZV9jaGFsbGVuZ2VfbWV0aG9kIjoiUzI1NiIsInJlZGlyZWN0X3VyaSI6Imh1YnNwYWNlLWFwcDovL2xvZ2lucmVkaXJlY3QiLCJjb2RlX2NoYWxsZW5nZSI6ImE5ejZ4d2lNek02NjlNMktYbmRhVlJ2QzhMQ3FDdjFINVd0UUxoNnhnd2sifX0.mHeidkIaJqs3hdMeHGxZOcDEAGmxFPQLnXIdCal1o-4', 'Content-Length': '67'}
session response: 200 - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">

<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="robots" content="noindex, nofollow">

    <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css">
    <link rel="icon" href="#" />
            <meta name="viewport" content="width=device-width,initial-scale=1"/>
    <title>Log in to Hubspace</title>
            <link href="/auth/resources/zpbf1/common/keycloak/web_modules/@patternfly/react-core/dist/styles/base.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/web_modules/@patternfly/react-core/dist/styles/app.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/node_modules/patternfly/dist/css/patternfly.min.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/node_modules/patternfly/dist/css/patternfly-additions.min.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/common/keycloak/lib/pficon/pficon.css" rel="stylesheet" />

            <link href="/auth/resources/zpbf1/login/hubspace/css/login.css" rel="stylesheet" />
            <link href="/auth/resources/zpbf1/login/hubspace/css/style.css" rel="stylesheet" />
    <script type="text/javascript">
        function getUrlVars() {
            var vars = [], hash;
            var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

            for(var i = 0; i < hashes.length; i++)
                {
                hash = hashes[i].split('=');
                vars.push(hash[0]);
                vars[hash[0]] = hash[1];
                }

            return vars;
        }
        function togglePassword(id) {
            var passwordField = document.getElementById(id);
            var passwordFieldToggle = document.getElementById('bt-toggle-' + id);
            if(passwordField.getAttribute('type') === 'password') {
                passwordField.setAttribute('type', 'text');
                passwordFieldToggle.value = 'Hide';
            } else {
                passwordField.setAttribute('type', 'password');
                passwordFieldToggle.value = 'Show';
            }
        }

        function clickLocale() {
            var localeDropdown = document.querySelector("#kc-locale ul");
            localeDropdown.style.display = localeDropdown.style.display != "block" ? "block" : "none";
        }


        document.addEventListener("DOMContentLoaded", function(event) {
            var usernameField = document.getElementById('username');
            var usernameInput = getUrlVars()['username'];
            if (usernameInput) {
                usernameField.value = decodeURIComponent(usernameInput);
            }

            var acceptChk = document.getElementById('acceptterms');
            if (acceptChk) {
                acceptChk.onclick = function () {
                    var login = document.getElementById('login-button');
                    console.log('Disabled ' + login.disabled);

                    if(acceptChk.checked) {
                        console.log('enable');
                        login.disabled = false; 
                    } else {
                        console.log('disable');
                        login.disabled = true; 
                    }
                }
            }
        }
   
        
        );
    </script>
<SCRIPT> if (typeof history.replaceState === 'function') {  history.replaceState({}, "some title", "https://accounts.hubspaceconnect.com/auth/realms/thd/login-actions/authenticate?execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&client_id=hubspace_android&tab_id=JwcAo1y86cw"); }</SCRIPT></head>

<body class="">
  <div class="login-pf-page">
    <div id="kc-header" class="login-pf-page-header">
      <img src="/auth/resources/zpbf1/login/hubspace/img/hubspace-mobile-logo.png" alt="Hubspace logo" width="628" height="106">
    </div>
    <div class="card-pf ">
      <header class="login-pf-header">

            <div id="kc-locale">
                <div id="kc-locale-wrapper" class="">
                    <div class="kc-dropdown" id="kc-locale-dropdown">
                        <button id="kc-current-locale-link" type="button" onClick="clickLocale()" tabindex=0>
                            English
                        </button>
                        <ul>
                                <li class="kc-dropdown-item"><a href="/auth/realms/thd/login-actions/authenticate?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;kc_locale=en">English</a></li>
                                <li class="kc-dropdown-item"><a href="/auth/realms/thd/login-actions/authenticate?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;kc_locale=fr">Fran�?ais</a></li>
                                <li class="kc-dropdown-item"><a href="/auth/realms/thd/login-actions/authenticate?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;kc_locale=es">Espa�?ol</a></li>
                        </ul>
                    </div>
                </div>
            </div>
                <h1 id="kc-page-title">        Sign In

</h1>
      </header>
      <div id="kc-content">
        <div id="kc-content-wrapper">

              <div class="alert alert-error">
                  
                  
                  <span class="fa fa-fw fa-exclamation-circle"></span>
                  
                  <span class="kc-feedback-text">Invalid username or password.</span>
              </div>

    <div id="kc-form" >
      <div id="kc-form-wrapper" >
            <form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="https://accounts.hubspaceconnect.com/auth/realms/thd/login-actions/authenticate?session_code=_666OIZbuqJZGLNwZQokFhMAsVK6PTPdvJQ-elYcR1s&amp;execution=3d17da1d-df31-42cd-8aa1-a3555b457e26&amp;client_id=hubspace_android&amp;tab_id=JwcAo1y86cw" method="post">
                <div class="form-group">
                    <label for="username" class="form-label">Email</label>

                        <input tabindex="0" id="username" class="form-control" name="username" value="REDACTED"  type="text" inputmode="email" autofocus autocomplete="off" />


                </div>

                <div class="form-group">
                    <label for="password" class="form-label">Password</label>
                    <input tabindex="0" id="password" class="form-control" name="password" type="password" autocomplete="off"/>
                    <input type="button" class="bt-password-toggle" id="bt-toggle-password" onClick="togglePassword('password')"  value='Show'/>
                </div>

                <div class="form-group login-pf-settings">
                    <div id="kc-form-options">
                    
                    </div>
                  
                  </div>

                  <div id="kc-form-buttons" class="form-group">
                      <input type="hidden" id="id-hidden-input" name="credentialId" />
                      <input tabindex="0" class="pf-c-button pf-m-primary btn-block btn-lg" name="login" id="kc-login" type="submit" value="Sign In"/>
                  </div>
                    <div id="kc-form-buttons" class="form-group">
                            <a tabindex="0" href="/auth/realms/thd/login-actions/registration?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw" class="btn reg-button">Register</a>

                    </div>

       
            </form>
        </div>

      </div>



              <div id="kc-info" class="login-pf-signup">
                  <div id="kc-info-wrapper" class="">
                                <span><a tabindex="0" href="/auth/realms/thd/login-actions/reset-credentials?client_id=hubspace_android&amp;tab_id=JwcAo1y86cw">Forgot Password?</a></span>

                  </div>
              </div>
             
        </div>
      </div>

    </div>
  </div>
</body>
</html>
 - {'cache-control': 'no-store, must-revalidate, max-age=0', 'x-xss-protection': '1; mode=block', 'x-frame-options': 'SAMEORIGIN', 'referrer-policy': 'no-referrer', 'content-security-policy': "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", 'date': 'Wed, 10 May 2023 03:08:05 GMT', 'x-robots-tag': 'none', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'x-content-type-options': 'nosniff', 'content-type': 'text/html;charset=utf-8', 'content-length': '8302', 'content-language': 'en'}
None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace.py", line 13, in getAccountID
    return self._user.getAccountID()
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 187, in getAccountID
    self._accountID = self.getInfo()['accountAccess'][0]['account']['accountId']
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 183, in getInfo
    return self.get("users/me")
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 161, in get
    headers=self._getHeaders(host),
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 150, in _getHeaders
    "authorization": self._getAuthorization(),
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 130, in _getAuthorization
    return "Bearer " + self._getAccessToken()
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 112, in _getAccessToken
    "refresh_token": self._getRefreshToken(),
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 98, in _getRefreshToken
    self._refresh_token = _getRefreshToken(self._username, self._password)
  File "/home/pi/.local/lib/python3.9/site-packages/hubspace/hubspace_user.py", line 60, in _getRefreshToken
    code = re.search(b'&code=(.+?)$', location).group(1)
  File "/usr/lib/python3.9/re.py", line 201, in search
    return _compile(pattern, flags).search(string)
TypeError: expected string or bytes-like object
>>> 

p.s. Great work! I hope you can keep this maintained (or even make it official).
One other small request would be to use the python logging module to make debugging changes like this easier in the future (and so that all issues have a standard format to them).
Thanks again for your efforts on this :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.