Didn't see the question till now sorry.
I'm not an expert in the area of authentication for PS, but I have written a bot with NodeJs.
When you connect to showdown, PS sends you a chalstring in the form of
|chalstr|str
. You'll want to make a HTTP GET or HTTP POST request to
http://play.pokemonshowdown.com/action.php
depending on what exactly your trying to do. (You can also use a HTTPS request).
- If your trying to login to an unregistered name, you'll want to make a GET request with
?act=getassertion&userid=userid&challstr=chalstr
where userid is the userid of the username you want to login to (all lowercase letters/numbers, no spaces, no symbols), and chalstr is your chalstring.
- If your trying to login to a registered name, you'll want to make a POST request with
act=login&name=userid&pass=password&challstr=chalstr}
where userid is the userid of the username you want to login to, password is the password (case sensetive of course), and chalstr is the your chalstring.
- If your trying to login to a name you have session cookies for, use
?act=upkeep&challstr=chalstr
where chalstr is your chalstring.
After sending the chalstr, you should get a response from the login server. This could be a number of things including:
;
meaning the name you chose is registered, and you did not provide a password, or provided an incorrect password.
- A message explaining why the login failed.
- If you made a POST login request: A JSON object starting with ] that contains what you need to login. You'll want to parse it and access the assertion property since youll need it to login.
- If you made a GET login to an unregistered name request: A string of characters that you will need to use to login (your assertion).
After getting your assertion, go ahead and send
/trn Username,0,assertion
where Username is your Username (case sensetive), and assertion is the assertion you got from your HTTP(S) request.
An example implementation that I use can be seen below:
JavaScript:
this.challstr = parts.join('|');
const reqOptions = {
hostname: "play.pokemonshowdown.com",
path: "/~~showdown/action.php",
agent: false,
};
let loginQuerystring;
if (!Config.pass) {
reqOptions.method = 'GET';
reqOptions.path += `?act=getassertion&userid=${toId(Config.nick)}&challstr=${this.challstr}`;
} else {
reqOptions.method = 'POST';
loginQuerystring = `act=login&name=${toId(Config.nick)}&pass=${Config.pass}&challstr=${this.challstr}`;
reqOptions.headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': loginQuerystring.length,
};
}
debug(`Sending login to ${reqOptions.path}${loginQuerystring ? ` | Data: ${loginQuerystring}` : ''}`);
const req = https.request(reqOptions, res => {
res.setEncoding('utf8');
let data = '';
res.on('data', chunk => {
data += chunk;
});
res.on('end', () => {
if (data === ';') {
console.log(`LOGIN FAILED - The name ${Config.nick} is registered and ${Config.pass ? 'an invalid' : 'no'} password was provided.`);
process.exit(1);
}
if (data.length < 50) {
console.log(`LOGIN FAILED - ${data}`);
process.exit(1);
}
if (data.indexOf('heavy load') > -1) {
console.log(`LOGIN FAILED - The login server is experiencing heavy load and cannot accommodate the bot's connection right now.`);
process.exit(1);
}
try {
data = JSON.parse(data.slice(1));
if (data.actionsuccess) {
data = data.assertion;
} else {
console.log(`Unable to login; the request was unsuccessful\n${JSON.stringify(data)}\n`);
process.exit(1);
}
} catch (e) {}
// Autojoining should be handled before sending /trn; since only
// eleven rooms can be autojoined at a time, leave any extras to
// be joined manually. (This allows the server to remember the first
// eleven if you happen to cut back on rooms)
if (Config.autojoin.length) {
const [autojoin, extra] = [Config.autojoin.slice(0, 11), Config.autojoin.slice(11)];
this.send(`|/autojoin ${autojoin.join(',')}`);
if (extra.length) this.extraJoin = extra;
}
this.send(`|/trn ${Config.nick},0,${data}`);
});
});
req.on('error', e => {
console.error(`Error while logging in: ${e.stack}`);
return;
});
if (loginQuerystring) req.write(loginQuerystring);
req.end();
See also:
https://github.com/Zarel/Pokemon-Showdown/blob/master/PROTOCOL.md#global-messages (chalstr)
Let me know if there are any other questions.