Moved repo

This commit is contained in:
RedDucks
2018-02-27 17:29:28 -05:00
parent 7fe019d8cc
commit a84a869098
25635 changed files with 29018 additions and 0 deletions

33
constants.js Normal file
View File

@@ -0,0 +1,33 @@
const ENV = process.env.NODE_ENV || 'dev';
let fs = require('fs'),
path = require('path');
module.exports = {
URL_ENDPOINTS: {
mii: 'http://mii-secure.account.riiu.net/'
},
LATEST_SYSTEM_VERSION: '0230',
MINIMUN_SYSTEM_VERSION: '0209',
PID_SORT_LIST: '0123456789',
VALID_CLIENT_ID_SECRET_PAIRS: {
// 'Key' is the client ID, 'Value' is the client secret
'a2efa818a34fa16b8afbc8a74eba3eda': 'c91cdb5658bd4954ade78533a339cf9a', // Possibly WiiU exclusive?
'daf6227853bcbdce3d75baee8332b': '3eff548eac636e2bf45bb7b375e7b6b0' // Possibly 3DS exclusive?
},
REGEX: {
HEADER_FORMATS: {
DEVICE_ID: /^\d{10}$/g,
REGION: /^\d+$/g,
SYSTEM_VERSION: /^\d+$/g,
}
},
REGION_CODES_NUM: {
'4': 'EUR',
'2': 'US'
},
REGION_CODES_STR: {
EUR: 4,
US: 2
},
}

18
db.js Normal file
View File

@@ -0,0 +1,18 @@
let mongoist = require('mongoist'),
config = require('./config.json'),
user_database_name = 'nintendo_acts',
user_database_collection_name = 'users',
user_database, user_collection;
let username = config.mongo.nintendo_acts.username;
let password = config.mongo.nintendo_acts.password;
let hostname = config.mongo.nintendo_acts.hostname;
let connection_string = 'mongodb://' + username + ':' + password + '@' + hostname + '/' + user_database_name + '?authSource=admin';
user_database = mongoist(connection_string);
user_collection = user_database.collection(user_database_collection_name);
module.exports = {
user_database: user_database,
user_collection: user_collection
};

59
debugger.js Normal file
View File

@@ -0,0 +1,59 @@
let ms = require('ms'),
colors = require('colors');
class Debugger {
constructor(title) {
this.title = title;
this.previous_time = new Date();
}
success(input) {
let current_time = new Date(),
time_taken = ms(ms(current_time - this.previous_time)),
suffix = '';
if (time_taken > 0) {
suffix = '-> '.green + (time_taken + 'ms').magenta;
}
let message = (this.title + ':').green.bold + ' ' + input.yellow.bold + ' ' + suffix.bold;
console.log(message);
this.previous_time = current_time;
}
error(input) {
let current_time = new Date(),
time_taken = ms(ms(current_time - this.previous_time)),
suffix = '';
if (time_taken > 0) {
suffix = '-> '.green + (time_taken + 'ms').magenta;
}
let message = (this.title + ':').red.bold + ' ' + input.yellow.bold + ' ' + suffix.bold;
console.log(message);
this.previous_time = current_time;
}
log(input) {
let current_time = new Date(),
time_taken = ms(ms(current_time - this.previous_time)),
suffix = '';
if (time_taken > 0) {
suffix = '-> '.green + (time_taken + 'ms').magenta;
}
let message = (this.title + ':').cyan.bold + ' ' + input.yellow.bold + ' ' + suffix.bold;
console.log(message);
this.previous_time = current_time;
}
}
module.exports = Debugger;

13
example.config.json Normal file
View File

@@ -0,0 +1,13 @@
{
"email": {
"address": "email@address.com",
"password": "password"
},
"mongo": {
"database_name": {
"username": "username",
"password": "password",
"hostname": "localhost"
}
}
}

254
helpers.js Normal file
View File

@@ -0,0 +1,254 @@
let constants = require('./constants'),
database = require('./db'),
pythonStruct = require('python-struct'),
bcrypt = require('bcryptjs'),
randtoken = require('rand-token'),
crypto = require('crypto');
async function generatePID() {
// Quick, dirty fix for PIDs
let pid = Math.floor(Math.random() * (4294967295 - 1000000000) + 1000000000);
let does_pid_inuse = await database.user_collection.findOne({
pid: pid
});
if (does_pid_inuse) {
return await generatePID();
}
return pid;
}
function generateRandID(length = 10) {
let id = '';
for (var i=0;i<length;i++) {
id += constants.PID_SORT_LIST.charAt(Math.floor(Math.random() * constants.PID_SORT_LIST.length));
}
return id;
}
async function generateEmailToken() {
let token = randtoken.generate(32);
let user = await database.user_collection.findOne({
'sensitive.email_confirms.token': token
});
if (user) {
return await generateEmailToken();
}
return token;
}
async function generateEmailCode() {
let code = generateRandID(6);
let user = await database.user_collection.findOne({
'sensitive.email_confirms.code': code
});
if (user) {
return await generateEmailCode();
}
return code;
}
function generateNintendoHashedPWrd(password, pid) {
let buff1 = pythonStruct.pack('<I', pid);
let buff2 = Buffer.from(password).toString('ascii');
let unpacked = new Buffer(bufferToHex(buff1) + '\x02eCF' + buff2, 'ascii'),
hashed = crypto.createHash('sha256').update(unpacked).digest().toString('hex');
return hashed;
}
function bufferToHex(buff) {
let result = '',
arr = buff.toString('hex').match(/.{1,2}/g);
for (var i=0;i<arr.length;i++) {
let char = arr[i],
char_code = char.charCodeAt();
result += String.fromCharCode(parseInt(char, 16));
}
result.replace(/\\/g, '&#92;');
return result;
}
async function doesUserExist(username) {
let user = await database.user_collection.findOne({
username: username.toLowerCase()
});
if (user) {
return true;
}
return false;
}
async function getUser(token) {
let user = await database.user_collection.findOne({
'sensitive.tokens.access.token': token
});
if (user) {
return user;
}
return null;
}
async function getUserBasic(token, email) {
let unpacked_token = Buffer.from(token, 'base64').toString().split(' ');
let user = await database.user_collection.findOne({
user_id_flat: unpacked_token[0].toLowerCase()
});
if (!user) {
return null;
}
if (user.email.address.address !== email) {
return null;
}
let hashed_password = generateNintendoHashedPWrd(unpacked_token[1], user.pid);
if (!bcrypt.compareSync(hashed_password, user.sensitive.password)) {
return null;
}
return user;
}
function generateAccessToken(payload) {
let token = crypto.createHash('md5').update(JSON.stringify(payload)).digest('hex');
return token;
}
function generateRefreshToken(payload) {
let token = crypto.createHash('md5').update(JSON.stringify(payload)).digest('hex');
return token;
}
function mapUser(user) {
let accounts = [];
let device_attributes = [];
user.accounts.forEach(account => {
account = account.account
let attributes = [];
account.attributes.forEach(attribute => {
attribute = attribute.attribute;
attributes.push({
attribute: {
id: attribute.id,
name: attribute.name,
updated_by: attribute.updated_by,
value: attribute.value,
}
});
});
accounts.push({
account: {
attributes: attributes,
domain: account.domain,
type: account.type,
username: account.username
}
})
});
user.device_attributes.device_attribute.forEach(device_attribute => {
let attribute = {
name: device_attribute.name,
value: device_attribute.value
};
if (device_attribute.created_date) {
attribute.created_date = device_attribute.created_date;
}
device_attributes.push({
device_attribute: attribute
});
});
let person = {
person: {
accounts: accounts,
active_flag: user.active_flag,
birth_date: user.birth_date,
country: user.country,
create_date: user.create_date,
device_attributes: device_attributes,
gender: user.gender,
language: user.language,
updated: user.updated,
marketing_flag: user.marketing_flag,
off_device_flag: user.off_device_flag,
pid: user.pid,
email: {
address: user.email.address.address,
id: user.email.id,
parent: user.email.address.parent,
primary: user.email.address.primary,
reachable: user.email.reachable,
type: user.email.address.type,
updated_by: user.email.updated_by,
validated: user.email.address.validated,
validated_date: user.updated
},
mii: {
status: user.mii.status,
data: user.mii.data.replace('\r\n', ''),
id: user.mii.id,
mii_hash: user.mii.mii_hash,
mii_images: [
{
mii_image: {
cached_url: user.mii.mii_images[0].cached_url,
id: user.mii.mii_images[0].id,
url: user.mii.mii_images[0].url,
type: user.mii.mii_images[0].type
}
}
],
name: user.mii.name,
primary: user.mii.primary
},
region: user.region,
tz_name: user.tz_name,
user_id: user.user_id,
utc_offset: user.utc_offset
}
}
return person;
}
module.exports = {
generatePID: generatePID,
generateRandID: generateRandID,
generateNintendoHashedPWrd: generateNintendoHashedPWrd,
doesUserExist: doesUserExist,
generateAccessToken: generateAccessToken,
generateRefreshToken: generateRefreshToken,
getUser: getUser,
getUserBasic: getUserBasic,
mapUser: mapUser,
generateEmailToken: generateEmailToken,
generateEmailCode: generateEmailCode,
}

31
mailer.js Normal file
View File

@@ -0,0 +1,31 @@
let nodemailer = require('nodemailer'),
config = require('./config.json');
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: config.email.address,
pass: config.email.password
}
});
function send(email, subject = 'No email subject provided', message = 'No email body provided') {
let options = {
from: 'pretendonetwork@gmail.com',
to: email,
subject: subject,
html: message
}
transporter.sendMail(options, (error, info) => {
if (error) {
console.log(error);
} else {
console.log(info);
}
});
}
module.exports = {
send: send
}

748
package-lock.json generated Normal file
View File

@@ -0,0 +1,748 @@
{
"name": "account.nintendo.net",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"accepts": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
"integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
"requires": {
"mime-types": "2.1.17",
"negotiator": "0.6.1"
}
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"basic-auth": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz",
"integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=",
"requires": {
"safe-buffer": "5.1.1"
}
},
"bcryptjs": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
"integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
},
"body-parser": {
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
"integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
"requires": {
"bytes": "3.0.0",
"content-type": "1.0.4",
"debug": "2.6.9",
"depd": "1.1.2",
"http-errors": "1.6.2",
"iconv-lite": "0.4.19",
"on-finished": "2.3.0",
"qs": "6.5.1",
"raw-body": "2.3.2",
"type-is": "1.6.15"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
}
}
},
"bson": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz",
"integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw="
},
"buffer-shims": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
"integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E="
},
"bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
},
"cli-table": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
"integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
"requires": {
"colors": "1.0.3"
},
"dependencies": {
"colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs="
}
}
},
"clone": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz",
"integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8="
},
"colors": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
},
"content-disposition": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookie": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
"integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
"requires": {
"clone": "1.0.3"
}
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"each-series": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/each-series/-/each-series-1.0.0.tgz",
"integrity": "sha1-+Ibmxm39sl7x/nNWQUbuXLR4r8s="
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"encodeurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
"integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA="
},
"es6-promise": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
"integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"express": {
"version": "4.16.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz",
"integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=",
"requires": {
"accepts": "1.3.4",
"array-flatten": "1.1.1",
"body-parser": "1.18.2",
"content-disposition": "0.5.2",
"content-type": "1.0.4",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "1.1.2",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"etag": "1.8.1",
"finalhandler": "1.1.0",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "2.0.2",
"qs": "6.5.1",
"range-parser": "1.2.0",
"safe-buffer": "5.1.1",
"send": "0.16.1",
"serve-static": "1.13.1",
"setprototypeof": "1.1.0",
"statuses": "1.3.1",
"type-is": "1.6.15",
"utils-merge": "1.0.1",
"vary": "1.1.2"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
}
}
},
"express-rate-limit": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-2.11.0.tgz",
"integrity": "sha512-KMZayDxj3Wr7zYuwTuDZj5hMW0nhnyJVBVCwMEVKwMdW6CkYh4vnfnUbRJYhKC0v6UuIbPerwKY0dqWmEzFjKA==",
"requires": {
"defaults": "1.0.3"
}
},
"express-subdomain": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz",
"integrity": "sha1-mQ75eUC39MKCPZWTZIt5voWKY4s="
},
"finalhandler": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
"integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
"requires": {
"debug": "2.6.9",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"statuses": "1.3.1",
"unpipe": "1.0.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
}
}
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs-extra": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
"requires": {
"graceful-fs": "4.1.11",
"jsonfile": "4.0.0",
"universalify": "0.1.1"
}
},
"graceful-fs": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
},
"http-errors": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
"integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
"requires": {
"depd": "1.1.1",
"inherits": "2.0.3",
"setprototypeof": "1.0.3",
"statuses": "1.3.1"
},
"dependencies": {
"depd": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
},
"setprototypeof": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
"integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
}
}
},
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ipaddr.js": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz",
"integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"json2xml": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/json2xml/-/json2xml-0.1.3.tgz",
"integrity": "sha1-mufCIL7dfGamaOJvesGC9nBOyiE="
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "4.1.11"
}
},
"long": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
},
"mime-db": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
},
"mime-types": {
"version": "2.1.17",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
"requires": {
"mime-db": "1.30.0"
}
},
"moment": {
"version": "2.20.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
"integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
},
"moment-timezone": {
"version": "0.5.14",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz",
"integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=",
"requires": {
"moment": "2.20.1"
}
},
"mongodb": {
"version": "2.2.34",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz",
"integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=",
"requires": {
"es6-promise": "3.2.1",
"mongodb-core": "2.1.18",
"readable-stream": "2.2.7"
}
},
"mongodb-core": {
"version": "2.1.18",
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz",
"integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=",
"requires": {
"bson": "1.0.4",
"require_optional": "1.0.1"
}
},
"mongoist": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/mongoist/-/mongoist-1.5.1.tgz",
"integrity": "sha512-dz72lBllGdon6aBawSUAIoJZM+FBUJSqqksU4RqtXJOik/OspMb/CBuMRb4iH0L7ffzS3qUVZsDaqnkuriPdoQ==",
"requires": {
"mongodb": "2.2.34"
}
},
"mongojs": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/mongojs/-/mongojs-2.4.1.tgz",
"integrity": "sha512-R344Q8ufjcqyFHO1CrxYboUBrEJwmsvMBtI8wsjCZq90mh/lzT0PBleAD6d1f8s07zeHSM2ebeu3OwMC4wxQlg==",
"requires": {
"each-series": "1.0.0",
"mongodb": "2.2.34",
"once": "1.4.0",
"parse-mongo-url": "1.1.1",
"readable-stream": "2.2.7",
"thunky": "1.0.2",
"to-mongodb-core": "2.0.0",
"xtend": "4.0.1"
}
},
"morgan": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz",
"integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=",
"requires": {
"basic-auth": "2.0.0",
"debug": "2.6.9",
"depd": "1.1.2",
"on-finished": "2.3.0",
"on-headers": "1.0.1"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
}
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
},
"negotiator": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
},
"nodemailer": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.4.2.tgz",
"integrity": "sha512-sstDxbCSPHDXrWRQhH++khr3yVU0CGvH2dCtAHOPQQ0lRR7xwq2txItEXckMpX481B/cN+0akER2bfExh7Gu/Q=="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"on-headers": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
"integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1.0.2"
}
},
"parse-mongo-url": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/parse-mongo-url/-/parse-mongo-url-1.1.1.tgz",
"integrity": "sha1-ZiON9fjnwMjKTNlw1KtqE3PrdbU="
},
"parseurl": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"pixl-xml": {
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/pixl-xml/-/pixl-xml-1.0.13.tgz",
"integrity": "sha1-W6cUCL3zeZTCOd0BJRwQxTwFh+M="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"proxy-addr": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz",
"integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=",
"requires": {
"forwarded": "0.1.2",
"ipaddr.js": "1.5.2"
}
},
"puid": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/puid/-/puid-1.0.7.tgz",
"integrity": "sha1-+mOKc317IEGQWdk5Za7TbKIOHIQ="
},
"python-struct": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/python-struct/-/python-struct-1.0.6.tgz",
"integrity": "sha512-r40v2MDFZKNBECMuo/oih6wInNEFXX0gmQgCJH4R7VULJsQDwcE95004r7A8iy1tDipgcZDyF8H6Tc2bhJdRZQ==",
"requires": {
"long": "3.2.0"
}
},
"qs": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
},
"rand-token": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/rand-token/-/rand-token-0.4.0.tgz",
"integrity": "sha512-FLNNsir2R+XY8LKsZ+8u/w0qZ4sGit7cpNdznsI77cAVob6UlVPueDKRyjJ3W1Q6FJLgAVH98JvlqqpSaL7NEQ=="
},
"range-parser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
},
"raw-body": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
"integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
"requires": {
"bytes": "3.0.0",
"http-errors": "1.6.2",
"iconv-lite": "0.4.19",
"unpipe": "1.0.0"
}
},
"readable-stream": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
"integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
"requires": {
"buffer-shims": "1.0.0",
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "1.0.3",
"util-deprecate": "1.0.2"
}
},
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"requires": {
"resolve-from": "2.0.0",
"semver": "5.4.1"
}
},
"resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
},
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
},
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
},
"send": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz",
"integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==",
"requires": {
"debug": "2.6.9",
"depd": "1.1.2",
"destroy": "1.0.4",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"etag": "1.8.1",
"fresh": "0.5.2",
"http-errors": "1.6.2",
"mime": "1.4.1",
"ms": "2.0.0",
"on-finished": "2.3.0",
"range-parser": "1.2.0",
"statuses": "1.3.1"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"serve-static": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz",
"integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==",
"requires": {
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"parseurl": "1.3.2",
"send": "0.16.1"
}
},
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
},
"statuses": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
"integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "5.1.1"
}
},
"thunky": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz",
"integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E="
},
"to-mongodb-core": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-mongodb-core/-/to-mongodb-core-2.0.0.tgz",
"integrity": "sha1-NZbsdhOsmtO5ioncua77pWnNJ+s="
},
"type-is": {
"version": "1.6.15",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
"integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
"requires": {
"media-typer": "0.3.0",
"mime-types": "2.1.17"
}
},
"universalify": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
"integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc="
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}
}
}

33
package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"name": "account.nintendo.net",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"cli-table": "^0.3.1",
"colors": "^1.1.2",
"express": "^4.16.2",
"express-rate-limit": "^2.11.0",
"express-subdomain": "^1.0.5",
"fs-extra": "^5.0.0",
"json2xml": "^0.1.3",
"moment": "^2.20.1",
"moment-timezone": "^0.5.14",
"mongoist": "^1.5.1",
"mongojs": "^2.4.1",
"morgan": "^1.9.0",
"ms": "^2.1.1",
"nodemailer": "^4.4.2",
"pixl-xml": "^1.0.13",
"puid": "^1.0.7",
"python-struct": "^1.0.6",
"rand-token": "^0.4.0"
}
}

55
routes/account/index.js Normal file
View File

@@ -0,0 +1,55 @@
let routes = require('express').Router(),
database = require('../../db'),
debug = require('../../debugger'),
route_debugger = new debug('Account Route');
route_debugger.success('Loading \'account\' API routes');
/**
* [GET]
* Replacement for: https://id.nintendo.net/account/email-confirmation
* Description: Verifies a user email via token
*/
routes.get('/email-confirmation', async (request, response) => {
let _GET = request.query;
if (!_GET.token) {
return response.send('ERROR: Invalid token');
}
let user = await database.user_collection.findOne({
'sensitive.email_confirms.token': _GET.token
});
if (!user) {
return response.send('ERROR: Invalid token');
}
user.email.reachable = 'Y';
user.email.validated = 'Y';
await database.user_collection.update({
pid: user.pid
}, {
$set: {
email: user.email
}
});
user.sensitive.email_confirms.token = null;
user.sensitive.email_confirms.code = null;
await database.user_collection.update({
pid: user.pid
}, {
$set: {
sensitive: user.sensitive
}
});
response.send(```
It has been confirmed that you can receive e-mails from Pretenod.<br>
The confirmation process is now complete.
```);
});
module.exports = routes;

109
routes/admin/index.js Normal file
View File

@@ -0,0 +1,109 @@
let routes = require('express').Router(),
json2xml = require('json2xml'),
database = require('../../db'),
constants = require('../../constants'),
debug = require('../../debugger'),
route_debugger = new debug('Admin Route');
route_debugger.success('Loading \'admin\' API routes');
/**
* [GET]
* Replacement for: https://account.nintendo.net/v1/api/admin/mapped_ids
* Description: Maps given input to expected output
*/
routes.all('/mapped_ids', async (request, response) => {
response.set('Content-Type', 'text/xml');
response.set('Server', 'Nintendo 3DS (http)');
response.set('X-Nintendo-Date', new Date().getTime());
let headers = request.headers,
_GET = request.query;
if (
!headers['x-nintendo-client-id'] ||
!headers['x-nintendo-client-secret'] ||
!constants.VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] ||
headers['x-nintendo-client-secret'] !== constants.VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']]
) {
let error = {
errors: {
error: {
cause: 'client_id',
code: '0004',
message: 'API application invalid or incorrect application credentials'
}
}
}
return response.send(json2xml(error));
}
if (
!_GET.output_type ||
!_GET.input_type ||
!_GET.input ||
_GET.input.trim() == ''
) {
let error = {
errors: {
error: {
cause: 'Bad Request',
code: '1600',
message: 'Unable to process request'
}
}
}
return response.send(json2xml(error));
}
let output = {
mapped_ids: [
]
}
_GET.input = _GET.input.split(',');
switch (true) {
case (_GET.input_type === 'user_id' && _GET.output_type === 'pid'):
await _GET.input.asyncForEach(async user_id => {
let user = await database.user_collection.findOne({
user_id_flat: user_id.toLowerCase(),
}),
out_id = null;
if (user) {
out_id = user.pid;
}
output.mapped_ids.push({
mapped_id: {
in_id: user_id,
out_id: out_id
}
});
});
break;
default:
_GET.input.forEach(input => {
output.mapped_ids.push({
mapped_id: {
in_id: input,
out_id: null
}
});
});
}
response.send(json2xml(output));
})
module.exports = routes;
Array.prototype.asyncForEach = async function (cb) {
for (let i=0;i<this.length;i++) {
await cb(this[i], i, this);
}
}

162
routes/content/index.js Normal file
View File

@@ -0,0 +1,162 @@
let routes = require('express').Router(),
path = require('path'),
helpers = require('../../helpers'),
constants = require('../../constants'),
fs = require('fs-extra'),
json2xml = require('json2xml'),
debug = require('../../debugger'),
route_debugger = new debug('Content Route');
route_debugger.success('Loading \'content\' API routes');
const VALID_REGIONS = [
'US', 'JP', 'GB', 'DE', 'FR'
];
const VALID_LANGUAGES = [
'en'
];
/**
* [GET]
* Replacement for: https://account.nintendo.net/v1/api/content/time_zones/REGION/LANGUAGE
* Description: Sends the client an XML list of timezones
*/
routes.get('/time_zones/:region/:language', (request, response) => {
response.set('Content-Type', 'text/xml');
response.set('Server', 'Nintendo 3DS (http)');
response.set('X-Nintendo-Date', new Date().getTime());
let headers = request.headers,
region = request.params.region,
language = request.params.language;
if (
!headers['x-nintendo-client-id'] ||
!headers['x-nintendo-client-secret'] ||
!constants.VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] ||
headers['x-nintendo-client-secret'] !== constants.VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']]
) {
let error = {
errors: {
error: {
cause: 'client_id',
code: '0004',
message: 'API application invalid or incorrect application credentials'
}
}
}
return response.send(json2xml(error));
}
if (!VALID_REGIONS.contains(region)
|| !VALID_LANGUAGES.contains(language)
|| !fs.pathExistsSync(path.join(__dirname, 'storage', 'timezones', region, language + '.xml'))) {
let error = {
errors: {
error: {
code: '0000',
message: 'Unknown error'
}
}
}
return response.send(json2xml(error));
}
response.sendFile(path.join(__dirname, 'storage', 'timezones', region, language + '.xml'));
});
/**
* [GET]
* Replacement for: https://account.nintendo.net/v1/api/content/agreements/TYPE/REGION/VERSION
* Description: Sends the client requested agreement
*/
routes.get('/agreements/:type/:region/:version', (request, response) => {
response.set('Content-Type', 'text/xml');
response.set('Server', 'Nintendo 3DS (http)');
response.set('X-Nintendo-Date', new Date().getTime());
let headers = request.headers,
type = request.params.type,
region = request.params.region,
version = request.params.version,
_GET = request.query;
// for some reason, the 3ds won't work if you have this.
// TODO: fix this for the 3ds
if (
!headers['x-nintendo-client-id'] ||
!headers['x-nintendo-client-secret'] ||
!constants.VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] ||
headers['x-nintendo-client-secret'] !== constants.VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']]
) {
let error = {
errors: {
error: {
cause: 'client_id',
code: '0004',
message: 'API application invalid or incorrect application credentials'
}
}
}
return response.send(json2xml(error));
}
if (!VALID_REGIONS.contains(region)) {
let error = {
errors: {
error: {
code: '0000',
message: 'Unknown error'
}
}
}
return response.send(json2xml(error));
}
if (!fs.pathExistsSync(path.join(__dirname, 'storage', 'agreements', type, region, version + '.xml'))) {
let error = {
errors: {
error: {
code: '1101',
message: 'No stored agreement found for this country: ' + region + ' type: ' + type + ' and version: ' + version
}
}
}
return response.send(json2xml(error));
}
/*
// ALSO NEED TO FIGURE OUT WHEN TO THROW ERROR 1102:
let error = {
errors: {
error: {
code: '1102',
message: 'No privacy policy found for this country ' + region + ' version ' + version
}
}
}
return response.send(json2xml(error));
// SEEMS TO BE RELATED TO THE `X-Nintendo-Region` HEADER.
// SETTING `X-Nintendo-Region` TO 4 (and `:region` is `US`) WHEN `:type` IS `Nintendo-Network-EULA` THROWS ERROR 1102
*/
response.sendFile(path.join(__dirname, 'storage', 'agreements', type, region, version + '.xml'));
});
module.exports = routes;
Array.prototype.contains = function(el) { // polyfill custom Array method
return this.indexOf(el) > -1;
}

View File

@@ -0,0 +1,95 @@
<agreements>
<agreement>
<country>US</country>
<language>en</language>
<language_name>English</language_name>
<publish_date>2014-09-29T20:07:35</publish_date>
<texts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="chunkedStoredAgreementText">
<agree_text>
<![CDATA[I Accept]]>
</agree_text>
<main_title>
<![CDATA[RiiU Network Services Agreement]]>
</main_title>
<non_agree_text>
<![CDATA[I Decline]]>
</non_agree_text>
<main_text index="1">
<![CDATA[
This is a custom service agreement made by RedDucks(s).
If you can see this, then the WiiU is connected to a custom server.
This means basic custom servers are possible.
However all WiiU multiplayer games, and some WiiU system features (for example the friends system) utilize UDP/PRUDP.
I have not cracked this protocol, and I probably never will as I lack the skills for it. Hopefully someone more skilled will lend me a hand with those areas.]]>
</main_text>
</texts>
<type>NINTENDO-NETWORK-EULA</type>
<version>0300</version>
</agreement>
<agreement>
<country>US</country>
<language>en</language>
<language_name>Español</language_name>
<publish_date>2014-09-29T20:07:35</publish_date>
<texts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="chunkedStoredAgreementText">
<agree_text>
<![CDATA[I Accept]]>
</agree_text>
<main_title>
<![CDATA[RiiU Network Services Agreement]]>
</main_title>
<non_agree_text>
<![CDATA[I Decline]]>
</non_agree_text>
<main_text index="1">
<![CDATA[
Este es un acuerdo de servicio personalizado hecho por RedDucks(s).
Si puede ver esto, entonces la WiiU está conectada a un servidor personalizado.
Esto significa que los servidores personalizados básicos son posibles.
Sin embargo, todos los juegos multijugador de WiiU y algunas características del sistema WiiU (por ejemplo, el sistema de amigos) utilizan UDP / PRUDP.
No he descifrado este protocolo, y probablemente nunca lo haré ya que carezco de las habilidades para ello. Espero que alguien más hábil me ayude con esas áreas.]]>
</main_text>
</texts>
<type>NINTENDO-NETWORK-EULA</type>
<version>0300</version>
</agreement>
<agreement>
<country>US</country>
<language>en</language>
<language_name>Français</language_name>
<publish_date>2014-09-29T20:07:35</publish_date>
<texts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="chunkedStoredAgreementText">
<agree_text>
<![CDATA[I Accept]]>
</agree_text>
<main_title>
<![CDATA[RiiU Network Services Agreement]]>
</main_title>
<non_agree_text>
<![CDATA[I Decline]]>
</non_agree_text>
<main_text index="1">
<![CDATA[
Ceci est un contrat de service personnalisé fait par RedDucks(s).
Si vous pouvez le voir, la WiiU est connectée à un serveur personnalisé.
Cela signifie que les serveurs personnalisés de base sont possibles.
Cependant, tous les jeux multijoueurs WiiU et certaines fonctionnalités du système WiiU (par exemple le système d'amis) utilisent UDP / PRUDP.
Je n'ai pas craqué ce protocole, et je ne le ferai probablement jamais car je n'ai pas les compétences pour le faire. J'espère que quelqu'un de plus compétent me prêtera un coup de main dans ces domaines.]]>
</main_text>
</texts>
<type>NINTENDO-NETWORK-EULA</type>
<version>0300</version>
</agreement>
</agreements>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>de</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>es</language><name>Madrid, París</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>fr</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>it</language><name>Madrid, Parigi</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>ja</language><name>マドリード、パリ</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><timezones><timezone><area>Europe/Andorra</area><language>en</language><name>Madrid, Paris</name><utc_offset>3600</utc_offset><order>0</order></timezone></timezones>

Some files were not shown because too many files have changed in this diff Show More