Feat: protobuf support (#831)

* feat: protobuf support

* Wuxiaworld (#31)

* wuxiaworld

* cleanup

* make .proto smaller

* add status

* fix date and partial freechapter

* fetchrpoto

* no more JSON.parse

* fix typeerrors

* fetchProto as type

* final draft

* cleanup summary

---------

Co-authored-by: K1ngfish3r <trulyihu@gmail.com>
This commit is contained in:
nyagami
2024-03-21 16:38:00 +07:00
committed by GitHub
parent 56eecc0a2e
commit 701dbc987c
5 changed files with 678 additions and 145 deletions
+50
View File
@@ -1,3 +1,5 @@
import { parse as parseProto } from 'protobufjs';
type FetchInit = {
headers?: Record<string, string | undefined> | Headers;
method?: string;
@@ -106,3 +108,51 @@ export const fetchText = async function (
return "";
}
};
interface ProtoRequestInit {
// merged .proto file
proto: string;
requestType: string;
requestData?: any;
responseType: string;
}
const BYTE_MARK = BigInt((1 << 8) - 1);
export const fetchProto = async function<ReturnType> (
protoInit: ProtoRequestInit,
url: string,
init?: FetchInit,
) {
const protoRoot = parseProto(protoInit.proto).root;
const RequestMessge = protoRoot.lookupType(protoInit.requestType);
if (RequestMessge.verify(protoInit.requestData)){
throw new Error('Invalid Proto');
}
// encode request data
const encodedrequest = RequestMessge.encode(protoInit.requestData).finish();
const requestLength = BigInt(encodedrequest.length);
const headers = new Uint8Array(
Array(5).fill(0).map((v, idx) => {
if(idx === 0) return 0;
return Number((requestLength >> BigInt(8 * (5 - idx - 1))) & BYTE_MARK);
})
);
init = await makeInit(init);
const bodyArray = new Uint8Array(headers.length + encodedrequest.length)
bodyArray.set(headers, 0)
bodyArray.set(encodedrequest, headers.length)
return fetch(url, {
method: 'POST',
...init,
body: bodyArray
} as RequestInit
).then(r => r.arrayBuffer())
.then(arr => {
// decode response data
const payload = new Uint8Array(arr);
const length = Number(BigInt(payload[1] << 24) | BigInt(payload[2] << 16) | BigInt(payload[3] << 8) | BigInt(payload[4]));
const ResponseMessage = protoRoot.lookupType(protoInit.responseType);
return ResponseMessage.decode(payload.slice(5, 5 + length));
}) as ReturnType
}