demo compile
parent
78b2b4b753
commit
26cb0eaef1
File diff suppressed because it is too large
Load Diff
37
src/App.tsx
37
src/App.tsx
|
@ -9,10 +9,15 @@ import {
|
||||||
TextField,
|
TextField,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import CountriesInput, { Country } from "./component/countriesInput";
|
import CountriesInput, { Country } from "./component/countriesInput";
|
||||||
import Telegram, { uploadBigFile } from "./telegram";
|
import Telegram, {
|
||||||
|
inputFile,
|
||||||
|
uploadBigFile,
|
||||||
|
sendFile,
|
||||||
|
downloadFile,
|
||||||
|
} from "./telegram";
|
||||||
import SendIcon from "@mui/icons-material/Send";
|
import SendIcon from "@mui/icons-material/Send";
|
||||||
import { User } from "./user";
|
import { User } from "./user";
|
||||||
import { Upload } from "@mui/icons-material";
|
import { Download, Upload } from "@mui/icons-material";
|
||||||
import ab2str from "./utils/arraybuffer2str";
|
import ab2str from "./utils/arraybuffer2str";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
@ -21,6 +26,7 @@ function App() {
|
||||||
let [phoneCodeHash, setPhoneCodeHash] = useState("");
|
let [phoneCodeHash, setPhoneCodeHash] = useState("");
|
||||||
let [country, setCountry] = useState({} as Country | null);
|
let [country, setCountry] = useState({} as Country | null);
|
||||||
let [user, setUser] = useState({} as User);
|
let [user, setUser] = useState({} as User);
|
||||||
|
let [fileDocument, setFileDocument] = useState({} as any);
|
||||||
const [fileList, setFileList] = useState([]);
|
const [fileList, setFileList] = useState([]);
|
||||||
|
|
||||||
let sendCode = () => {
|
let sendCode = () => {
|
||||||
|
@ -62,7 +68,6 @@ function App() {
|
||||||
Telegram.call("messages.sendMessage", {
|
Telegram.call("messages.sendMessage", {
|
||||||
peer: {
|
peer: {
|
||||||
_: "inputPeerSelf",
|
_: "inputPeerSelf",
|
||||||
user_id: user.id,
|
|
||||||
},
|
},
|
||||||
message: "ice",
|
message: "ice",
|
||||||
random_id: (10000 + Math.random() * (100000 - 10000))
|
random_id: (10000 + Math.random() * (100000 - 10000))
|
||||||
|
@ -81,7 +86,18 @@ function App() {
|
||||||
console.log("uploadFile:", fileList);
|
console.log("uploadFile:", fileList);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
uploadBigFile(fileList[0]?.bytes)
|
uploadBigFile(fileList[0]?.bytes)
|
||||||
.then((file_id) => console.log("uploadFile ret:", file_id))
|
.then((file) => {
|
||||||
|
console.log("uploadFile ret:", file);
|
||||||
|
sendFile(
|
||||||
|
// @ts-ignore
|
||||||
|
inputFile(file.file_id, file.total_part, fileList[0].name),
|
||||||
|
// @ts-ignore
|
||||||
|
fileList[0].type
|
||||||
|
).then((result) => {
|
||||||
|
console.log("sendFile ret:", result);
|
||||||
|
setFileDocument(result.updates[1].message.media);
|
||||||
|
});
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log("uploadFile error:", error);
|
console.log("uploadFile error:", error);
|
||||||
alert(error);
|
alert(error);
|
||||||
|
@ -93,7 +109,7 @@ function App() {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = function (event) {
|
reader.onload = function (event) {
|
||||||
if (event.target && event.target.result) {
|
if (event.target && event.target.result) {
|
||||||
let bytes = ab2str(event.target.result as ArrayBuffer);
|
let bytes = event.target.result;
|
||||||
console.log(bytes);
|
console.log(bytes);
|
||||||
e.target.files[0].bytes = bytes;
|
e.target.files[0].bytes = bytes;
|
||||||
setFileList(e.target.files);
|
setFileList(e.target.files);
|
||||||
|
@ -102,6 +118,14 @@ function App() {
|
||||||
reader.readAsArrayBuffer(e.target.files[0]);
|
reader.readAsArrayBuffer(e.target.files[0]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let download = () => {
|
||||||
|
console.log("download:", fileDocument);
|
||||||
|
downloadFile(fileDocument).catch((error) => {
|
||||||
|
console.log("download error:", error);
|
||||||
|
alert(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="sm">
|
<Container maxWidth="sm">
|
||||||
<Paper
|
<Paper
|
||||||
|
@ -160,6 +184,9 @@ function App() {
|
||||||
<Button variant={"contained"} onClick={uploadFile} endIcon={<Upload />}>
|
<Button variant={"contained"} onClick={uploadFile} endIcon={<Upload />}>
|
||||||
上传
|
上传
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button variant={"contained"} onClick={download} endIcon={<Download />}>
|
||||||
|
下载
|
||||||
|
</Button>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
|
@ -54,7 +54,7 @@ function CountriesInput(props: {
|
||||||
})}
|
})}
|
||||||
sx={{ width: 300 }}
|
sx={{ width: 300 }}
|
||||||
onChange={(_event, value) => {
|
onChange={(_event, value) => {
|
||||||
props.onChange(value);
|
props.onChange(value as Country);
|
||||||
}}
|
}}
|
||||||
getOptionLabel={(option) => option.default_name}
|
getOptionLabel={(option) => option.default_name}
|
||||||
renderOption={(props, option) => (
|
renderOption={(props, option) => (
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
declare module "mtproton/envs/browser";
|
declare module "mtproton/envs/browser";
|
||||||
|
declare module "mtproton/src/utils/common";
|
||||||
|
|
161
src/telegram.ts
161
src/telegram.ts
|
@ -1,6 +1,5 @@
|
||||||
import Client from "mtproton/envs/browser";
|
import Client from "mtproton/envs/browser";
|
||||||
import between from "./utils/rand";
|
import between from "./utils/rand";
|
||||||
import exp from "constants";
|
|
||||||
|
|
||||||
class TelegramHelper {
|
class TelegramHelper {
|
||||||
private client: any;
|
private client: any;
|
||||||
|
@ -8,12 +7,12 @@ class TelegramHelper {
|
||||||
this.client = new Client({
|
this.client = new Client({
|
||||||
api_id: appID,
|
api_id: appID,
|
||||||
api_hash: appHash,
|
api_hash: appHash,
|
||||||
test: true,
|
test: false,
|
||||||
});
|
});
|
||||||
|
this.client.setDefaultDc(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
async call(method: string, params?: object, options?: object): Promise<any> {
|
||||||
async call(method: string, params?: object, options?: object) {
|
|
||||||
try {
|
try {
|
||||||
return await this.client.call(method, params, options);
|
return await this.client.call(method, params, options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -36,34 +35,42 @@ class TelegramHelper {
|
||||||
|
|
||||||
const dcId = Number(dcIdAsString);
|
const dcId = Number(dcIdAsString);
|
||||||
|
|
||||||
if (type === "PHONE") {
|
// if (type === "PHONE") {
|
||||||
await this.client.setDefaultDc(dcId);
|
await this.client.setDefaultDc(dcId);
|
||||||
} else {
|
// } else {
|
||||||
Object.assign(options, { dcId });
|
// Object.assign(options, { dcId });
|
||||||
}
|
// }
|
||||||
|
|
||||||
return this.call(method, params, options);
|
return this.call(method, params, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadBigFile(bytes: string): Promise<number> {
|
async function uploadBigFile(
|
||||||
|
bytes: ArrayBuffer
|
||||||
|
): Promise<{ file_id: number; total_part: number }> {
|
||||||
let file_id = between(10000, 99999);
|
let file_id = between(10000, 99999);
|
||||||
console.log("file_id", file_id);
|
console.log("file_id", file_id);
|
||||||
|
|
||||||
const file_total_parts = Math.ceil(bytes.length / 524288);
|
let uploadBytes = new Uint8Array(bytes);
|
||||||
|
console.log("uploading file", bytes);
|
||||||
|
const file_total_parts = Math.ceil(uploadBytes.length / 524288);
|
||||||
console.log("file_total_parts", file_total_parts);
|
console.log("file_total_parts", file_total_parts);
|
||||||
for (let i = 0; i < file_total_parts; i++) {
|
for (let i = 0; i < file_total_parts; i++) {
|
||||||
console.log("push part: ", i);
|
console.log("push part: ", i);
|
||||||
try {
|
try {
|
||||||
|
let tempBytes = uploadBytes.slice(i * 524288, (i + 1) * 524288);
|
||||||
|
if (i === file_total_parts - 1) {
|
||||||
|
tempBytes = uploadBytes.slice(i * 524288);
|
||||||
|
}
|
||||||
|
console.log("tempBytes", tempBytes);
|
||||||
let finished = await Telegram.call("upload.saveBigFilePart", {
|
let finished = await Telegram.call("upload.saveBigFilePart", {
|
||||||
file_id: file_id,
|
file_id: file_id,
|
||||||
file_part: i,
|
file_part: i,
|
||||||
file_total_parts: file_total_parts,
|
file_total_parts: file_total_parts,
|
||||||
bytes: bytes.slice(i * 524288, (i + 1) * 524288),
|
bytes: tempBytes,
|
||||||
});
|
});
|
||||||
if (finished) {
|
if (finished) {
|
||||||
console.log("finished");
|
console.log("finished");
|
||||||
|
@ -76,12 +83,138 @@ async function uploadBigFile(bytes: string): Promise<number> {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("uploaded");
|
console.log("uploaded");
|
||||||
return file_id;
|
return { file_id: file_id, total_part: file_total_parts };
|
||||||
|
}
|
||||||
|
|
||||||
|
function inputFile(file_id: number, part_number: number, file_name: string) {
|
||||||
|
return {
|
||||||
|
_: "inputFileBig",
|
||||||
|
id: file_id,
|
||||||
|
parts: part_number,
|
||||||
|
name: file_name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendFile(inputFile: any, type: string) {
|
||||||
|
let random_id = between(10000, 99999);
|
||||||
|
console.log("random_id", random_id);
|
||||||
|
return Telegram.call("messages.sendMedia", {
|
||||||
|
peer: {
|
||||||
|
_: "inputPeerSelf",
|
||||||
|
},
|
||||||
|
media: {
|
||||||
|
_: "inputMediaUploadedDocument",
|
||||||
|
file: inputFile,
|
||||||
|
mime_type: type,
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
_: "documentAttributeFilename",
|
||||||
|
file_name: inputFile.name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
random_id: between(10000, 99999),
|
||||||
|
message: "test",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadFile(fileDocument: any) {
|
||||||
|
let partSize = 1024 * 1024;
|
||||||
|
const file_total_parts = Math.ceil(fileDocument.document.size / partSize);
|
||||||
|
|
||||||
|
let results = [];
|
||||||
|
for (let i = 0; i < file_total_parts; i++) {
|
||||||
|
try {
|
||||||
|
let result = await Telegram.call("upload.getFile", {
|
||||||
|
location: {
|
||||||
|
_: "inputDocumentFileLocation",
|
||||||
|
id: fileDocument.document.id,
|
||||||
|
access_hash: fileDocument.document.access_hash,
|
||||||
|
file_reference: fileDocument.document.file_reference,
|
||||||
|
thumb_size: "",
|
||||||
|
},
|
||||||
|
limit: partSize,
|
||||||
|
offset: partSize * i,
|
||||||
|
});
|
||||||
|
console.log("result", result);
|
||||||
|
results.push(result);
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("messages.getDocument:", results);
|
||||||
|
let bytes = new Uint8Array(fileDocument.document.size);
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
for (let j = 0; j < results[i].bytes.length; j++) {
|
||||||
|
bytes[i * partSize + j] = results[i].bytes[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let downloadBytes = bytes;
|
||||||
|
console.log("downloadBytes", downloadBytes);
|
||||||
|
let blob = new Blob([downloadBytes], {
|
||||||
|
type: fileDocument.document.mime_type,
|
||||||
|
});
|
||||||
|
let url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = fileDocument.document.attributes[0].file_name;
|
||||||
|
a.click();
|
||||||
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const appID = 18987971;
|
const appID = 18987971;
|
||||||
const appHash = "fcfd9e6ed3f9e48a360bb57cc0d59d98";
|
const appHash = "fcfd9e6ed3f9e48a360bb57cc0d59d98";
|
||||||
let Telegram = new TelegramHelper(appID, appHash);
|
let Telegram = new TelegramHelper(appID, appHash);
|
||||||
|
|
||||||
|
function hexStringToArrayBuffer(hexString: string) {
|
||||||
|
// remove the leading 0x
|
||||||
|
hexString = hexString.replace(/^0x/, "");
|
||||||
|
|
||||||
|
// ensure even number of characters
|
||||||
|
if (hexString.length % 2 != 0) {
|
||||||
|
console.log(
|
||||||
|
"WARNING: expecting an even number of characters in the hexString"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for some non-hex characters
|
||||||
|
let bad = hexString.match(/[G-Z\s]/i);
|
||||||
|
if (bad) {
|
||||||
|
console.log("WARNING: found non-hex characters", bad);
|
||||||
|
}
|
||||||
|
|
||||||
|
// split the string into pairs of octets
|
||||||
|
let pairs = hexString.match(/[\dA-F]{2}/gi);
|
||||||
|
|
||||||
|
// convert the octets to integers
|
||||||
|
// @ts-ignore
|
||||||
|
let integers = pairs.map(function (s: string) {
|
||||||
|
return parseInt(s, 16);
|
||||||
|
});
|
||||||
|
|
||||||
|
let array = new Uint8Array(integers);
|
||||||
|
console.log(array);
|
||||||
|
|
||||||
|
return array.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrayBufferToHex(arrayBuffer: ArrayBuffer) {
|
||||||
|
if (typeof arrayBuffer !== "object" || arrayBuffer === null) {
|
||||||
|
throw new TypeError("Expected input to be an ArrayBuffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
let view = new Uint8Array(arrayBuffer);
|
||||||
|
let result = "";
|
||||||
|
let value;
|
||||||
|
|
||||||
|
for (let i = 0; i < view.length; i++) {
|
||||||
|
value = view[i].toString(16);
|
||||||
|
result += value.length === 1 ? "0" + value : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export default Telegram;
|
export default Telegram;
|
||||||
export { uploadBigFile };
|
export { uploadBigFile, inputFile, sendFile, downloadFile };
|
||||||
|
|
|
@ -5,4 +5,16 @@ function ArraybufferToStr(buffer: ArrayBuffer) {
|
||||||
return decoder.decode(uint8);
|
return decoder.decode(uint8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function ab2str(buf: ArrayBuffer) {
|
||||||
|
// return String.fromCharCode.apply(null, buf as Uint16Array);
|
||||||
|
// }
|
||||||
|
// function str2ab(str: string) {
|
||||||
|
// let buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
|
||||||
|
// let bufView = new Uint16Array(buf);
|
||||||
|
// for (let i = 0, strLen = str.length; i < strLen; i++) {
|
||||||
|
// bufView[i] = str.charCodeAt(i);
|
||||||
|
// }
|
||||||
|
// return buf;
|
||||||
|
// }
|
||||||
|
//
|
||||||
export default ArraybufferToStr;
|
export default ArraybufferToStr;
|
||||||
|
|
Loading…
Reference in New Issue