moving smapi soap related classes into smapi.ts

This commit is contained in:
simojenki
2021-02-26 12:03:51 +11:00
parent 6c5b78cd6e
commit 12fe09dd7f
6 changed files with 215 additions and 213 deletions

View File

@@ -1,2 +1,134 @@
import crypto from "crypto";
import { Express } from "express";
import { listen } from "soap";
import { readFileSync } from "fs";
import path from "path";
import logger from "./logger";
export type GetAppLinkResult = { getAppLinkResult: { authorizeAccount: { appUrlStringId: string, deviceLink: { regUrl: string, linkCode:string,showLinkCode:boolean }} } }
import { LinkCodes } from "./link_codes";
export const LOGIN_ROUTE = "/login"
export const SOAP_PATH = "/ws/sonos";
export const STRINGS_ROUTE = "/sonos/strings.xml";
export const PRESENTATION_MAP_ROUTE = "/sonos/presentationMap.xml";
const WSDL_FILE = path.resolve(
__dirname,
"Sonoswsdl-1.19.4-20190411.142401-3.wsdl"
);
export type GetAppLinkResult = {
getAppLinkResult: {
authorizeAccount: {
appUrlStringId: string;
deviceLink: { regUrl: string; linkCode: string; showLinkCode: boolean };
};
};
};
export type GetDeviceAuthTokenResult = {
getDeviceAuthTokenResult: {
authToken: string;
privateKey: string;
userInfo: {
nickname: string;
userIdHashCode: string;
};
};
};
class SonosSoap {
linkCodes: LinkCodes;
webAddress: string;
constructor(webAddress: string, linkCodes: LinkCodes) {
this.webAddress = webAddress;
this.linkCodes = linkCodes;
}
getAppLink(): GetAppLinkResult {
const linkCode = this.linkCodes.mint();
return {
getAppLinkResult: {
authorizeAccount: {
appUrlStringId: "AppLinkMessage",
deviceLink: {
regUrl: `${this.webAddress}${LOGIN_ROUTE}?linkCode=${linkCode}`,
linkCode: linkCode,
showLinkCode: false,
},
},
},
};
}
getDeviceAuthToken({
linkCode,
}: {
linkCode: string;
}): GetDeviceAuthTokenResult {
const association = this.linkCodes.associationFor(linkCode);
if (association) {
return {
getDeviceAuthTokenResult: {
authToken: association.authToken.value,
privateKey: association.authToken.version,
userInfo: {
nickname: association.nickname,
userIdHashCode: crypto
.createHash("sha256")
.update(association.userId)
.digest("hex"),
},
},
};
} else {
throw {
Fault: {
faultcode: "Client.NOT_LINKED_RETRY",
faultstring: "Link Code not found retry...",
detail: {
ExceptionInfo: "NOT_LINKED_RETRY",
SonosError: "5",
},
},
};
}
}
}
function bindSmapiSoapServiceToExpress(app: Express, soapPath:string, webAddress: string, linkCodes: LinkCodes) {
const sonosSoap = new SonosSoap(webAddress, linkCodes);
const soapyService = listen(
app,
soapPath,
{
Sonos: {
SonosSoap: {
getAppLink: () => sonosSoap.getAppLink(),
getDeviceAuthToken: ({ linkCode }: { linkCode: string }) =>
sonosSoap.getDeviceAuthToken({ linkCode }),
},
},
},
readFileSync(WSDL_FILE, "utf8")
);
soapyService.log = (type, data) => {
switch (type) {
case "info":
logger.info({ level: "info", data });
break;
case "warn":
logger.warn({ level: "warn", data });
break;
case "error":
logger.error({ level: "error", data });
break;
default:
logger.debug({ level: "debug", data });
}
};
}
export default bindSmapiSoapServiceToExpress;