├── .gitignore ├── server ├── data │ └── .gitkeep ├── recovery.html ├── strftime.js ├── index.html └── server.js ├── capt1.png ├── capt2.png ├── Cargo.toml ├── README.md ├── spark ├── server.js └── index.html ├── index.html ├── crawler_595732.html ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /server/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /capt1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayuusweetfish/treasure-hole/HEAD/capt1.png -------------------------------------------------------------------------------- /capt2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayuusweetfish/treasure-hole/HEAD/capt2.png -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "treasurehole" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | reqwest = { version = "0.11", features = ["socks"] } 8 | tokio = { version = "1", features = ["full"] } 9 | serde_json = "1.0" 10 | bytebuffer = "0.2.1" 11 | bytes = "*" 12 | futures = "0.3" 13 | regex = "1" 14 | iui = { git = "https://github.com/rust-native-ui/libui-rs", branch = "trunk" } 15 | chrono = "0.4" 16 | -------------------------------------------------------------------------------- /server/recovery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treasure hole 6 | 7 | 8 | 26 | 27 |
28 |

问题恢复

29 | 所有中途出现问题的备份会在整理后发布在这里,请使用抓取时使用的 token 访问。若不慎丢失,请通过 GitHub 联系 30 |
31 | 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 🌐 在线版 2 | 3 | 在线版位于 [hole.botany.run](https://hole.botany.run/)。登录凭据不会被保存,理论上也不会泄露,但为安全起见,完成备份后建议注销后重新登录。 4 | 5 | ⚠️ 在线版抓取到的文字和图片可能会被合并归档,参与其他的树洞备份项目。此过程不会保留任何个人信息(如关注列表、投票),独立的备份压缩包将在事后全部删除,望知晓。 6 | 7 | ## 说明 8 | 9 | ![ ](capt1.png) 10 | 11 | #### 操作方法 12 | 13 | 1. 首先获得自己的令牌(token),具体参见树洞 [#595705](https://web.thuhole.com/##595705)。 14 | 2. 把 token 粘贴在“身份令牌”一栏中。 15 | 3. 选择“引用层数”,如指定为 2,则会保存所有关注的树洞、它们提到的树洞以及【它们提到的树洞中提到的树洞】。 16 | 4. 取决于访问树洞的方式,可能需要填写网络代理。若不了解,可尝试留空。 17 | 5. 点击“开始”,等待即可。 18 | 19 | 备份的内容会集中存放到程序所在位置旁边,其中包含一个网页 `index.html`,用浏览器打开之即可。 20 | 21 | ![ ](capt2.png) 22 | 23 | #### 常见问题 24 | 25 | 1. 提示“登录凭据已过期” 26 | - token 由数字与字母组成,请检查是否粘贴了多余内容如冒号、空格等。 27 | 2. 点击开始后长时间无反应 28 | - 请在树洞中提问并附上当前访问树洞的方式。 29 | 30 | Enjoy 31 | 32 | ## crawler\_595732.html 33 | 34 | 另外,如果已经使用 [#595732](https://web.thuhole.com/##595732) 提供的方法爬取关注列表,请直接下载 [crawler\_595732.html](https://raw.githubusercontent.com/kawa-yoiko/treasure-hole/master/crawler_595732.html),在浏览器中打开,选择爬取到的 JSON 文件即可。 35 | 36 | ## 技术信息 37 | 38 | 主程序:使用 [Rust](https://www.rust-lang.org/) 编译器构建。 39 | 40 | ```sh 41 | cargo build --release 42 | 43 | # 运行图形界面 44 | cargo run --release 45 | # 从命令行获取参数 46 | cargo run --release -- [] 47 | ``` 48 | 49 | 服务端:使用 [Deno](https://deno.land/) 运行。 50 | 51 | ```sh 52 | cd server 53 | deno run --allow-net --allow-run --allow-read server.js 54 | ``` 55 | -------------------------------------------------------------------------------- /server/strftime.js: -------------------------------------------------------------------------------- 1 | /* Port of strftime() by T. H. Doan (https://thdoan.github.io/strftime/) 2 | * 3 | * Day of year (%j) code based on Joe Orost's answer: 4 | * http://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366 5 | * 6 | * Week number (%V) code based on Taco van den Broek's prototype: 7 | * http://techblog.procurios.nl/k/news/view/33796/14863/calculate-iso-8601-week-and-year-in-javascript.html 8 | */ 9 | export function strftime(sFormat, date) { 10 | if (!(date instanceof Date)) date = new Date(); 11 | var nDay = date.getDay(), 12 | nDate = date.getDate(), 13 | nMonth = date.getMonth(), 14 | nYear = date.getFullYear(), 15 | nHour = date.getHours(), 16 | aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 17 | aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 18 | aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], 19 | isLeapYear = function() { 20 | return (nYear%4===0 && nYear%100!==0) || nYear%400===0; 21 | }, 22 | getThursday = function() { 23 | var target = new Date(date); 24 | target.setDate(nDate - ((nDay+6)%7) + 3); 25 | return target; 26 | }, 27 | zeroPad = function(nNum, nPad) { 28 | return ((Math.pow(10, nPad) + nNum) + '').slice(1); 29 | }; 30 | return sFormat.replace(/%[a-z]/gi, function(sMatch) { 31 | return (({ 32 | '%a': aDays[nDay].slice(0,3), 33 | '%A': aDays[nDay], 34 | '%b': aMonths[nMonth].slice(0,3), 35 | '%B': aMonths[nMonth], 36 | '%c': date.toUTCString(), 37 | '%C': Math.floor(nYear/100), 38 | '%d': zeroPad(nDate, 2), 39 | '%e': nDate, 40 | '%F': date.toISOString().slice(0,10), 41 | '%G': getThursday().getFullYear(), 42 | '%g': (getThursday().getFullYear() + '').slice(2), 43 | '%H': zeroPad(nHour, 2), 44 | '%I': zeroPad((nHour+11)%12 + 1, 2), 45 | '%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth>1 && isLeapYear()) ? 1 : 0), 3), 46 | '%k': nHour, 47 | '%l': (nHour+11)%12 + 1, 48 | '%m': zeroPad(nMonth + 1, 2), 49 | '%n': nMonth + 1, 50 | '%M': zeroPad(date.getMinutes(), 2), 51 | '%p': (nHour<12) ? 'AM' : 'PM', 52 | '%P': (nHour<12) ? 'am' : 'pm', 53 | '%s': Math.round(date.getTime()/1000), 54 | '%S': zeroPad(date.getSeconds(), 2), 55 | '%u': nDay || 7, 56 | '%V': (function() { 57 | var target = getThursday(), 58 | n1stThu = target.valueOf(); 59 | target.setMonth(0, 1); 60 | var nJan1 = target.getDay(); 61 | if (nJan1!==4) target.setMonth(0, 1 + ((4-nJan1)+7)%7); 62 | return zeroPad(1 + Math.ceil((n1stThu-target)/604800000), 2); 63 | })(), 64 | '%w': nDay, 65 | '%x': date.toLocaleDateString(), 66 | '%X': date.toLocaleTimeString(), 67 | '%y': (nYear + '').slice(2), 68 | '%Y': nYear, 69 | '%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'), 70 | '%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1') 71 | }[sMatch] || '') + '') || sMatch; 72 | }); 73 | } 74 | -------------------------------------------------------------------------------- /spark/server.js: -------------------------------------------------------------------------------- 1 | // deno run --allow-net --allow-read --allow-env % 2 | 3 | import { serve } from 'https://deno.land/std@0.117.0/http/server.ts'; 4 | import { strftime } from '../server/strftime.js'; 5 | 6 | // Do not go gentle into that good night 7 | 8 | const addr = ':1937'; 9 | 10 | const indexHtmlContents = await Deno.readFile('index.html'); 11 | 12 | // id => { log, fin, list }; 13 | const ctx = {}; 14 | 15 | Deno.env.set('TZ', 'Asia/Shanghai'); 16 | const timestr = (ts) => strftime('%F %H:%M:%S', new Date(ts * 1000)); 17 | 18 | const handler = async (req) => { 19 | const method = req.method; 20 | const path = new URL(req.url).pathname; 21 | 22 | if (method === 'GET' && path === '/') { 23 | return new Response(indexHtmlContents, { status: 200 }); 24 | } 25 | 26 | const requestMatch = path.match(/^\/request\/([a-z0-9]{1,50})$/); 27 | if (method === 'POST' && requestMatch !== null) { 28 | const token = requestMatch[1]; 29 | const date = strftime('%Y%m%d-%H%M%S'); 30 | const id = `${date}-${token}`; 31 | if (ctx[id] !== undefined) { 32 | return new Response(null, { status: 400 }); 33 | } 34 | const log = []; 35 | const list = []; 36 | ctx[id] = { 37 | log, 38 | list, 39 | }; 40 | const worker = async () => { 41 | console.log(`${strftime('%F %H:%M:%S')} Starting ${id}`); 42 | let count = 0; 43 | for (let page = 1; ; page++) { 44 | const obj = await (await fetch( 45 | `https://tapi.thuhole.com/v3/contents/post/attentions?page=${page}`, { 46 | headers: { 'TOKEN': token }, 47 | } 48 | )).json(); 49 | if (obj.code !== 0) { 50 | log.splice(0, 0, `树洞返回错误:\n${obj.msg}\n======`); 51 | break; 52 | } 53 | if (obj.count === 0) break; 54 | for (const post of obj.data) { 55 | list.push( 56 | `=== #${post.pid} === ${timestr(post.timestamp)} 57 | ${post.text}` 58 | ); 59 | const cmts = obj.comments[post.pid]; 60 | if (cmts) { 61 | for (const cmt of cmts) 62 | list.push( 63 | `[${cmt.name}] ${timestr(cmt.timestamp)} 64 | ${cmt.text}` 65 | ); 66 | if (post.reply > cmts.length) { 67 | list.push( 68 | `(还有 ${post.reply - cmts.length} 条)` 69 | ); 70 | } 71 | } 72 | } 73 | count += obj.data.length; 74 | const word = (Math.random() <= 0.01 ? '咕咕。' : '咕嘟。'); 75 | log.splice(0, 0, `${word}第 ${page} 页,合计 ${count} 条`); 76 | if (log.length >= 50) log.pop(); 77 | } 78 | log.splice(0, 0, `完成`); 79 | log.splice(1, 0, `有效期 10 分钟,请及时下载~\n======`); 80 | ctx[id].fin = true; 81 | console.log(`${strftime('%F %H:%M:%S')} Finished ${id}`); 82 | // Remove after 10 minutes 83 | setTimeout(() => delete ctx[id], 600000); 84 | }; 85 | worker(); // Do not await 86 | return new Response(id, { status: 200 }); 87 | } 88 | 89 | const logMatch = path.match(/^\/log\/([a-z0-9\-]{1,50})$/); 90 | if (method === 'GET' && logMatch !== null) { 91 | const id = logMatch[1]; 92 | const c = ctx[id]; 93 | if (c === undefined) { 94 | return new Response('Not found', { status: 404 }); 95 | } 96 | return new Response(JSON.stringify({ 97 | fin: !!c.fin, 98 | log: c.log, 99 | }), { status: 200 }); 100 | } 101 | 102 | const downloadMatch = path.match(/^\/download\/([a-z0-9\-]{1,50})$/); 103 | if (method === 'GET' && downloadMatch !== null) { 104 | const id = downloadMatch[1]; 105 | const c = ctx[id]; 106 | if (c === undefined) { 107 | return new Response('Not found', { status: 404 }); 108 | } 109 | return new Response(c.list.join('\n\n'), { 110 | headers: { 111 | 'Content-Type': 'text/plain', 112 | 'Content-Disposition': 'attachment; filename="attentions.txt"', 113 | }, 114 | status: 200, 115 | }); 116 | } 117 | 118 | return new Response('Not found', { status: 404 }); 119 | }; 120 | 121 | console.log(`Running at http://localhost${addr}/`); 122 | await serve(handler, { addr }); 123 | -------------------------------------------------------------------------------- /spark/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treasure hole 6 | 7 | 8 | 79 | 80 |
81 |
Token
83 | 84 |
85 |
86 | 87 | 88 |
89 | 90 |
91 | 93 |
94 | 95 | 142 | 143 | -------------------------------------------------------------------------------- /server/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treasure hole 6 | 7 | 8 | 79 | 80 |
81 |
Token
83 | 84 |
85 |
层数
87 | 88 |
89 |
90 | 91 | 92 |
93 | 94 |
95 | 97 |
98 | 99 | 147 | 148 | -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | import { serve } from 'https://deno.land/std@0.117.0/http/server.ts'; 2 | import { strftime } from './strftime.js'; 3 | import staticFiles from "https://deno.land/x/static_files@1.1.4/mod.ts"; 4 | 5 | const addr = ':1213'; 6 | 7 | const EXEC_PATH = '../target/release/treasurehole'; 8 | // Use proxy if needed, e.g. 9 | // const PROXY = 'http://127.0.0.1:1087'; 10 | const PROXY = ''; 11 | 12 | const indexHtmlContents = await Deno.readFile('index.html'); 13 | 14 | const downloads = staticFiles('./data', { 15 | prefix: '/download' 16 | }); 17 | 18 | // id => { log }; 19 | const ctx = {}; 20 | 21 | const retryRun = async (opts) => { 22 | while (true) { 23 | try { 24 | const proc = Deno.run(opts); 25 | return proc; 26 | } catch (ex) { 27 | console.log(`Arranging for retry: ${opts.cmd}`); 28 | await new Promise((resolve) => setTimeout(resolve, 5000)) 29 | continue; 30 | } 31 | } 32 | } 33 | 34 | const handler = async (req) => { 35 | const method = req.method; 36 | const path = new URL(req.url).pathname; 37 | 38 | if (method === 'GET' && path === '/') { 39 | return new Response(indexHtmlContents, { status: 200 }); 40 | } 41 | 42 | const requestMatch = path.match(/^\/request\/([a-z0-9]{1,50})\/(\d\d?)$/); 43 | if (method === 'POST' && requestMatch !== null) { 44 | const token = requestMatch[1]; 45 | const levels = parseInt(requestMatch[2], 10); 46 | if (levels < 0 || levels > 10) { 47 | return new Response(null, { status: 400 }); 48 | } 49 | const date = strftime('%Y%m%d-%H%M%S'); 50 | const id = `${date}-${token}`; 51 | if (ctx[id] !== undefined) { 52 | return new Response(null, { status: 400 }); 53 | } 54 | const log = []; 55 | ctx[id] = { 56 | log, 57 | }; 58 | const worker = async () => { 59 | console.log(`Starting ${id} (levels = ${levels})`); 60 | const cmd = [ 61 | EXEC_PATH, 62 | token, 63 | levels.toString(), 64 | `./data/${id}`, 65 | PROXY, 66 | ]; 67 | const proc = await retryRun({ 68 | cmd, 69 | stdout: 'null', 70 | stderr: 'piped', 71 | }); 72 | const buf = new Uint8Array(4096); 73 | const decoder = new TextDecoder(); 74 | const line = new Uint8Array(4096); 75 | let linePtr = 0; 76 | while (true) { 77 | const bytesRead = await proc.stderr.read(buf); 78 | if (bytesRead === null) break; 79 | for (let i = 0; i < bytesRead; i++) { 80 | if (buf[i] === 10) { 81 | log.splice(0, 0, decoder.decode(line.slice(0, linePtr))); 82 | if (log.length >= 100) log.pop(); 83 | linePtr = 0; 84 | } else if (linePtr < line.length) { 85 | line[linePtr++] = buf[i]; 86 | } 87 | } 88 | } 89 | if (linePtr !== 0) { 90 | log.splice(0, 0, decoder.decode(line.slice(0, linePtr))); 91 | if (log.length >= 100) log.pop(); 92 | } 93 | // Successful? 94 | if (log[0] === '完成') { 95 | log.splice(0, 0, '压缩中\n======'); 96 | // Compress 97 | const proc = await retryRun({ 98 | cwd: './data', 99 | cmd: ['zip', id, '-r', id], 100 | stdout: 'null', 101 | stderr: 'null', 102 | }); 103 | const { code } = await proc.status(); 104 | if (code !== 0) { 105 | log.splice(0, 0, `压缩过程出现意外问题:${code}`); 106 | } else { 107 | log.splice(0, 0, '完成'); 108 | } 109 | const rmProc = await retryRun({ 110 | cmd: ['rm', '-rf', `./data/${id}`], 111 | stdout: 'null', 112 | stderr: 'null', 113 | }); 114 | await rmProc.status(); 115 | } 116 | ctx[id].fin = true; 117 | console.log(`Finished ${id}`); 118 | // Remove after 10 minutes 119 | setTimeout(() => delete ctx[id], 600000); 120 | }; 121 | worker(); // Do not await 122 | return new Response(id, { status: 200 }); 123 | } 124 | 125 | const logMatch = path.match(/^\/log\/([a-z0-9\-]{1,50})$/); 126 | if (method === 'GET' && logMatch !== null) { 127 | const id = logMatch[1]; 128 | const c = ctx[id]; 129 | if (c === undefined) { 130 | return new Response('Not found', { status: 404 }); 131 | } 132 | return new Response(JSON.stringify({ 133 | fin: !!c.fin, 134 | log: c.log, 135 | }), { status: 200 }); 136 | } 137 | 138 | const zipMatch = path.match(/^\/download\/([a-z0-9\-]{1,50}).zip$/); 139 | if (method === 'GET' && zipMatch !== null) { 140 | const id = zipMatch[1]; 141 | console.log(`Download ${id}`); 142 | return downloads({ 143 | request: req, 144 | respondWith: r => r, 145 | }); 146 | } 147 | 148 | if (method === 'GET' && path === '/recovery') { 149 | console.log(`Recovery`); 150 | const htmlContents = await Deno.readFile('recovery.html'); 151 | return new Response(htmlContents, { status: 200 }); 152 | } 153 | 154 | return new Response('Not found', { status: 404 }); 155 | }; 156 | 157 | console.log(`Running at http://localhost${addr}/`); 158 | await serve(handler, { addr }); 159 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treasure hole 6 | 7 | 8 | 9 | 113 | 114 |
115 |
116 | 117 | 165 | 166 | 167 | 253 | 254 | -------------------------------------------------------------------------------- /crawler_595732.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treasure hole 6 | 7 | 8 | 9 | 113 | 114 | 115 |
116 |
117 |

JSON File

118 | 119 | 120 |
121 |
122 | 160 | 161 |
162 |
163 | 164 | 212 | 213 | 360 | 361 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![windows_subsystem = "windows"] 2 | 3 | use std::io::Write; 4 | 5 | #[derive(Debug)] 6 | pub struct StringError { 7 | s: String, 8 | } 9 | 10 | impl StringError { 11 | pub fn new(s: String) -> Self { 12 | Self { s } 13 | } 14 | } 15 | 16 | impl std::convert::From<&str> for StringError { 17 | fn from(s: &str) -> Self { 18 | Self { s: s.to_string() } 19 | } 20 | } 21 | impl std::convert::From for StringError { 22 | fn from(s: String) -> Self { 23 | Self { s } 24 | } 25 | } 26 | 27 | impl std::fmt::Display for StringError { 28 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 29 | write!(f, "{}", self.s) 30 | } 31 | } 32 | impl std::error::Error for StringError {} 33 | 34 | type DynResult = Result>; 35 | 36 | async fn fetch_bytes(client: &reqwest::Client, url: &str) -> DynResult { 37 | let resp = client.get(url).send().await?; 38 | let status = resp.status(); 39 | if status.as_u16() != 200 { 40 | return Err(Box::new(StringError::from(format!("HTTP Status: {} {}", 41 | status.as_u16(), 42 | status.canonical_reason().unwrap_or("Unknown reason"))))); 43 | } 44 | 45 | let body = resp.bytes().await?; 46 | Ok(body) 47 | } 48 | 49 | async fn fetch_json(client: &reqwest::Client, url: String) -> DynResult<(String, serde_json::Value)> { 50 | let body = fetch_bytes(client, &url).await?; 51 | let body = String::from_utf8((&body).to_vec())?; 52 | match serde_json::de::from_str::(&body) { 53 | Ok(r) => Ok((body, r)), 54 | _ => Err(Box::new(StringError::from("Cannot parse JSON document"))), 55 | } 56 | } 57 | 58 | macro_rules! expect_json_type { 59 | // Optional types 60 | ($value:expr, Option $variant:tt) => { 61 | match $value { 62 | Some(serde_json::Value::$variant(x)) => x, 63 | _ => return Err(Box::new(StringError::from( 64 | format!("Incorrect JSON format (line {})", line!())))), 65 | } 66 | }; 67 | // Direct types 68 | ($value:expr, $variant:tt) => { 69 | match $value { 70 | serde_json::Value::$variant(x) => x, 71 | _ => return Err(Box::new(StringError::from( 72 | format!("Incorrect JSON format (line {})", line!())))), 73 | } 74 | }; 75 | } 76 | 77 | async fn fetch_attn_pids( 78 | client: &reqwest::Client, 79 | tx: tokio::sync::mpsc::Sender<(bool, String)>, 80 | ) -> DynResult> { 81 | let mut pids = vec![]; 82 | 83 | for page in 1.. { 84 | let url = format!("https://tapi.thuhole.com/v3/contents/post/attentions?page={}", page); 85 | let (_text, attns) = fetch_json(&client, url).await?; 86 | 87 | let attns = expect_json_type!(attns, Object); 88 | // println!("{:?}", attns); 89 | 90 | // Return code 91 | let code = expect_json_type!(attns.get("code"), Option Number).as_i64(); 92 | match code { 93 | Some(code) if code != 0 => { 94 | return Err(Box::new(StringError::from(format!( 95 | "Incorrect code {}; message {}", code, 96 | expect_json_type!(attns.get("msg"), Option String) 97 | )))); 98 | }, 99 | None => return Err(Box::new(StringError::from("Incorrect JSON format"))), 100 | _ => {}, 101 | } 102 | 103 | let posts = expect_json_type!(attns.get("data"), Option Array); 104 | if posts.len() == 0 { break; } 105 | 106 | for post in posts { 107 | let pid = match expect_json_type!(post.get("pid"), Option Number).as_u64() { 108 | Some(x) => x, 109 | None => return Err(Box::new(StringError::from("Incorrect JSON format"))), 110 | }; 111 | pids.push(pid); 112 | } 113 | 114 | tx.send((false, format!("获取收藏列表(第 {} 页,{} 条)", page, pids.len()))).await.unwrap(); 115 | // XXX: debug use 116 | // if page >= 1 { break; } 117 | } 118 | 119 | // XXX: debug use 120 | // return Ok(pids[0..5].to_vec()); 121 | 122 | Ok(pids) 123 | } 124 | 125 | async fn fetch_and_save_image( 126 | client: &reqwest::Client, 127 | url: &str, 128 | wd: &std::path::Path, 129 | ) -> DynResult { 130 | let url = format!("https://i.thuhole.com/{}", url); 131 | let bytes = fetch_bytes(client, &url).await?; 132 | 133 | let paths = url.split('/').collect::>(); 134 | let mut wd_path = std::path::PathBuf::from(wd); 135 | wd_path.push("images"); 136 | wd_path.push(paths.last().unwrap()); 137 | let mut f = std::fs::File::create(&wd_path)?; 138 | f.write_all(&bytes)?; 139 | 140 | Ok(()) 141 | } 142 | 143 | async fn fetch_and_save_posts( 144 | client: &reqwest::Client, 145 | tx: tokio::sync::mpsc::Sender<(bool, String)>, 146 | pids: &[u64], 147 | f: &mut std::fs::File, 148 | wd: &std::path::Path, 149 | ) -> DynResult> { 150 | let mut images = vec![]; 151 | let mut ref_pids = vec![]; 152 | 153 | let re_post_ref = regex::Regex::new(r"#(\d{1,})").unwrap(); 154 | 155 | // Fetch each post and write to file 156 | for (i, pid_chunk) in pids.chunks(10).enumerate() { 157 | let text_futs = pid_chunk.iter().map(|&pid| { 158 | let url = format!("https://tapi.thuhole.com/v3/contents/post/detail?pid={}", pid); 159 | fetch_json(&client, url) 160 | }); 161 | tx.send((false, format!("获取帖子内容({}/{},起始 #{})", 162 | std::cmp::min((i + 1) * 10, pids.len()), 163 | pids.len(), 164 | pid_chunk[0], 165 | ))).await.unwrap(); 166 | let results = futures::future::try_join_all(text_futs).await?; 167 | 168 | for (post_text, post_json) in results { 169 | // Error? 170 | let code = expect_json_type!(post_json.get("code"), Option Number).as_i64(); 171 | match code { 172 | Some(-101) => { 173 | /*tx.send((false, format!("跳过(信息:{})", 174 | expect_json_type!(post_json.get("msg"), Option String) 175 | ))).await.unwrap();*/ 176 | continue; 177 | }, 178 | Some(code) if code != 0 => { 179 | return Err(Box::new(StringError::from(format!( 180 | "Incorrect code {}; message {}", code, 181 | expect_json_type!(post_json.get("msg"), Option String) 182 | )))); 183 | }, 184 | None => return Err(Box::new(StringError::from("Incorrect JSON format"))), 185 | _ => {}, 186 | } 187 | 188 | f.write_all(post_text.as_bytes())?; 189 | f.write_all(",\n".as_bytes())?; 190 | f.flush()?; 191 | 192 | // Look for image contents 193 | // Post 194 | let post = expect_json_type!(post_json.get("post"), Option Object); 195 | let post_type = expect_json_type!(post.get("type"), Option String); 196 | if post_type == "image" { 197 | let image_url = expect_json_type!(post.get("url"), Option String); 198 | images.push(image_url.clone()); 199 | } 200 | // Replies 201 | let replies = expect_json_type!(post_json.get("data"), Option Array); 202 | for reply in replies { 203 | let reply_type = expect_json_type!(reply.get("type"), Option String); 204 | if reply_type == "image" { 205 | let image_url = expect_json_type!(reply.get("url"), Option String); 206 | images.push(image_url.clone()); 207 | } 208 | } 209 | 210 | // Look for post references 211 | // Post 212 | let post_text = expect_json_type!(post.get("text"), Option String); 213 | for cap in re_post_ref.captures_iter(post_text) { 214 | if let Ok(id) = cap[1].parse::() { 215 | ref_pids.push(id); 216 | } 217 | } 218 | } 219 | } 220 | 221 | for (i, image_chunk) in images.chunks(10).enumerate() { 222 | let image_futs = image_chunk.iter().map( 223 | |image_url| fetch_and_save_image(client, &image_url, wd) 224 | ); 225 | tx.send((false, format!("保存图片({}/{})", 226 | std::cmp::min((i + 1) * 10, images.len()), 227 | images.len(), 228 | ))).await.unwrap(); 229 | futures::future::try_join_all(image_futs).await?; 230 | } 231 | 232 | Ok(ref_pids) 233 | } 234 | 235 | async fn fetch_attn_all( 236 | client: &reqwest::Client, 237 | tx: tokio::sync::mpsc::Sender<(bool, String)>, 238 | wd: &std::path::Path, 239 | ref_levels: u32, 240 | ) -> DynResult { 241 | let attn_pids = fetch_attn_pids(&client, { let tx = tx.clone(); tx }).await?; 242 | // println!("{:?}", attn_pids); 243 | 244 | match std::fs::remove_dir_all(wd) { 245 | Err(e) if e.kind() != std::io::ErrorKind::NotFound => { 246 | return Err(Box::new(StringError::from("Cannot remove existing contents"))); 247 | }, 248 | _ => {}, 249 | } 250 | std::fs::create_dir(wd)?; 251 | 252 | let mut wd_path = std::path::PathBuf::from(wd); 253 | wd_path.push("data.js"); 254 | // tx.send((false, format!("database: {:?}", wd_path))).await.unwrap(); 255 | let mut f = std::fs::File::create(wd_path)?; 256 | f.write_all("const posts = [\n".as_bytes())?; 257 | 258 | let mut img_wd_path = std::path::PathBuf::from(wd); 259 | img_wd_path.push("images"); 260 | // tx.send((false, format!("images: {:?}", img_wd_path))).await.unwrap(); 261 | std::fs::create_dir(img_wd_path)?; 262 | 263 | // Deduplication 264 | let mut fetched_pids = std::collections::HashSet::new(); 265 | 266 | fetched_pids.extend(attn_pids.iter().copied()); 267 | let mut ref_pids = fetch_and_save_posts(client, { let tx = tx.clone(); tx }, &attn_pids, &mut f, wd).await?; 268 | 269 | // Delimiter to denote 'reachable by references' 270 | f.write_all("'---',\n".as_bytes())?; 271 | 272 | for i in 0..ref_levels { 273 | tx.send((false, format!("=== 跟随第 {} 层引用 ===", i + 1))).await.unwrap(); 274 | ref_pids = ref_pids.iter() 275 | .copied() 276 | .filter(|pid| !fetched_pids.contains(pid)) 277 | .collect::>(); 278 | fetched_pids.extend(attn_pids.iter().copied()); 279 | // tx.send((false, format!("referenced: {:?}", ref_pids))).await.unwrap(); 280 | ref_pids = fetch_and_save_posts(client, { let tx = tx.clone(); tx }, &ref_pids, &mut f, wd).await?; 281 | } 282 | 283 | f.write_all("];\n".as_bytes())?; 284 | 285 | // Write HTML 286 | let mut html_wd_path = std::path::PathBuf::from(wd); 287 | html_wd_path.push("index.html"); 288 | tx.send((false, format!("保存位置为 {:?}", html_wd_path))).await.unwrap(); 289 | let mut f = std::fs::File::create(html_wd_path)?; 290 | f.write_all(include_bytes!("../index.html"))?; 291 | 292 | Ok(()) 293 | } 294 | 295 | async fn fetch_everything( 296 | token: &str, proxy: &str, target_dir: &std::path::Path, 297 | ref_levels: u32, 298 | tx: tokio::sync::mpsc::Sender<(bool, String)>, 299 | ) -> DynResult { 300 | tx.send((false, format!("开始备份,内容将保存在 {:?}\n======", target_dir))).await.unwrap(); 301 | 302 | let mut headers = reqwest::header::HeaderMap::new(); 303 | headers.insert("TOKEN", reqwest::header::HeaderValue::from_str(token)?); 304 | let mut client_builder = reqwest::Client::builder() 305 | .default_headers(headers); 306 | if proxy != "" { 307 | client_builder = client_builder.proxy(reqwest::Proxy::https(proxy)?); 308 | } 309 | let client = client_builder.build()?; 310 | 311 | fetch_attn_all(&client, tx, target_dir, ref_levels).await?; 312 | 313 | Ok(()) 314 | } 315 | 316 | async fn main_gui() -> DynResult { 317 | let mut ui = iui::UI::init().unwrap(); 318 | 319 | use iui::controls::*; 320 | 321 | let mut win = Window::new(&ui, "hole", 360, 540, WindowType::HasMenubar); 322 | let mut grid = LayoutGrid::new(&ui); 323 | grid.set_padded(&ui, true); 324 | win.set_child(&ui, grid.clone()); 325 | 326 | let ent_token = Entry::new(&ui); 327 | let mut ent_reflv = Spinbox::new(&ui, 0, 10); 328 | let ent_proxy = Entry::new(&ui); 329 | let controls: [(&str, Control); 3] = [ 330 | ("身份令牌", ent_token.clone().into()), 331 | ("引用层数", ent_reflv.clone().into()), 332 | ("网络代理", ent_proxy.clone().into()), 333 | ]; 334 | ent_reflv.set_value(&ui, 2); 335 | 336 | for (i, (text, control)) in controls.iter().enumerate() { 337 | let label = Label::new(&ui, text); 338 | grid.append(&ui, label.clone(), 0, i as i32, 1, 1, 339 | GridExpand::Neither, GridAlignment::Fill, GridAlignment::Fill); 340 | grid.append(&ui, control.clone(), 1, i as i32, 1, 1, 341 | GridExpand::Horizontal, GridAlignment::Fill, GridAlignment::Fill); 342 | } 343 | 344 | let ent_reflv_text = Entry::new(&ui); 345 | grid.append(&ui, ent_reflv_text.clone(), 1, 1, 1, 1, 346 | GridExpand::Horizontal, GridAlignment::Fill, GridAlignment::Fill); 347 | ui.set_enabled(ent_reflv_text.clone(), false); 348 | ui.set_shown(ent_reflv_text.clone(), false); 349 | 350 | let mut btn_go = Button::new(&ui, "开始"); 351 | grid.append(&ui, btn_go.clone(), 0, 4, 2, 1, 352 | GridExpand::Horizontal, GridAlignment::Fill, GridAlignment::Fill); 353 | 354 | let log_disp = MultilineEntry::new(&ui); 355 | ui.set_enabled(log_disp.clone(), false); 356 | ui.set_shown(log_disp.clone(), false); 357 | grid.append(&ui, log_disp.clone(), 0, 5, 2, 1, 358 | GridExpand::Both, GridAlignment::Fill, GridAlignment::Fill); 359 | 360 | let handle = tokio::runtime::Handle::current(); 361 | let (tx, mut rx) = tokio::sync::mpsc::channel(10); 362 | let mut logs = vec![]; 363 | 364 | btn_go.on_clicked(&ui, { 365 | let mut ui = ui.clone(); 366 | let controls = controls.clone(); 367 | let ent_reflv = ent_reflv.clone(); 368 | let mut ent_reflv_text = ent_reflv_text.clone(); 369 | let btn_go = btn_go.clone(); 370 | let log_disp = log_disp.clone(); 371 | move |_| { 372 | let token = ent_token.value(&ui); 373 | let proxy = ent_proxy.value(&ui); 374 | let reflv = ent_reflv.value(&ui) as u32; 375 | // Directory of executable 376 | let mut wd = std::env::current_exe().unwrap(); 377 | wd.pop(); 378 | let time = chrono::offset::Local::now().format("%Y%m%d-%H%M"); 379 | wd.push(&format!("{}-{}", time, token)); 380 | 381 | // Disable controls 382 | for (_, control) in &controls { 383 | ui.set_enabled(control.clone(), false); 384 | } 385 | ent_reflv_text.set_value(&ui, &ent_reflv.value(&ui).to_string()); 386 | ui.set_shown(ent_reflv.clone(), false); 387 | ui.set_shown(ent_reflv_text.clone(), true); 388 | ui.set_enabled(btn_go.clone(), false); 389 | ui.set_shown(log_disp.clone(), true); 390 | 391 | // Spawn thread 392 | let tx = tx.clone(); 393 | handle.spawn(async move { 394 | let msg = match fetch_everything( 395 | &token, 396 | &proxy, 397 | &wd, 398 | reflv, 399 | { let tx = tx.clone(); tx }, 400 | ).await { 401 | Err(e) => format!("出现意外问题,请在汇报时附上以下信息:\n{}\n======", e), 402 | _ => "完成".to_string(), 403 | }; 404 | tx.send((true, msg)).await.unwrap(); 405 | }); 406 | } 407 | }); 408 | 409 | win.show(&ui); 410 | 411 | let mut event_loop = ui.event_loop(); 412 | event_loop.on_tick(&ui, { 413 | let mut ui = ui.clone(); 414 | let controls = controls.clone(); 415 | let ent_reflv = ent_reflv.clone(); 416 | let ent_reflv_text = ent_reflv_text.clone(); 417 | let mut log_disp = log_disp.clone(); 418 | let logs = &mut logs; 419 | move || { 420 | if let Ok((term, text)) = rx.try_recv() { 421 | // Add to log 422 | logs.insert(0, text); 423 | if logs.len() >= 500 { logs.pop(); } 424 | log_disp.set_value(&ui, &logs.join("\n")); 425 | 426 | if term { 427 | // Enable controls 428 | for (_, control) in &controls { 429 | ui.set_enabled(control.clone(), true); 430 | } 431 | ui.set_shown(ent_reflv.clone(), true); 432 | ui.set_shown(ent_reflv_text.clone(), false); 433 | ui.set_enabled(btn_go.clone(), true); 434 | } 435 | } 436 | } 437 | }); 438 | event_loop.run_delay(&ui, 10); 439 | 440 | Ok(()) 441 | } 442 | 443 | #[tokio::main] 444 | async fn main() -> DynResult { 445 | let args = std::env::args().collect::>(); 446 | if args.len() >= 4 { 447 | let (tx, mut rx) = tokio::sync::mpsc::channel(10); 448 | let join_handle = tokio::runtime::Handle::current().spawn(async move { 449 | loop { 450 | if let Some((term, text)) = rx.recv().await { 451 | eprintln!("{}", text); 452 | std::io::stderr().flush().unwrap(); 453 | if term { break; } 454 | } else { 455 | break; 456 | } 457 | } 458 | }); 459 | let result = fetch_everything( 460 | &args[1], 461 | if args.len() >= 5 { &args[4] } else { "" }, 462 | std::path::Path::new(&args[3]), 463 | args[2].parse()?, 464 | tx.clone(), 465 | ).await; 466 | if let Err(e) = result { 467 | tx.clone().send((true, format!("出现意外问题:\n{}\n======", e))).await.unwrap(); 468 | } else { 469 | tx.clone().send((true, "完成".to_string())).await.unwrap(); 470 | } 471 | join_handle.await?; 472 | std::io::stderr().flush().unwrap(); 473 | } else { 474 | main_gui().await?; 475 | } 476 | Ok(()) 477 | } 478 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.17.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "0.7.18" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "ansi_term" 31 | version = "0.12.1" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 34 | dependencies = [ 35 | "winapi", 36 | ] 37 | 38 | [[package]] 39 | name = "atty" 40 | version = "0.2.14" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 43 | dependencies = [ 44 | "hermit-abi", 45 | "libc", 46 | "winapi", 47 | ] 48 | 49 | [[package]] 50 | name = "autocfg" 51 | version = "1.0.1" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 54 | 55 | [[package]] 56 | name = "backtrace" 57 | version = "0.3.63" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" 60 | dependencies = [ 61 | "addr2line", 62 | "cc", 63 | "cfg-if 1.0.0", 64 | "libc", 65 | "miniz_oxide", 66 | "object", 67 | "rustc-demangle", 68 | ] 69 | 70 | [[package]] 71 | name = "base64" 72 | version = "0.13.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 75 | 76 | [[package]] 77 | name = "bindgen" 78 | version = "0.54.0" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "66c0bb6167449588ff70803f4127f0684f9063097eca5016f37eb52b92c2cf36" 81 | dependencies = [ 82 | "bitflags", 83 | "cexpr", 84 | "cfg-if 0.1.10", 85 | "clang-sys", 86 | "clap", 87 | "env_logger", 88 | "lazy_static", 89 | "lazycell", 90 | "log", 91 | "peeking_take_while", 92 | "proc-macro2", 93 | "quote", 94 | "regex", 95 | "rustc-hash", 96 | "shlex", 97 | "which", 98 | ] 99 | 100 | [[package]] 101 | name = "bitflags" 102 | version = "1.3.2" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 105 | 106 | [[package]] 107 | name = "bumpalo" 108 | version = "3.8.0" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" 111 | 112 | [[package]] 113 | name = "bytebuffer" 114 | version = "0.2.1" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "e822a21389d388828152aeae8bb43049196b09076e2a138f53351d8cf6576cf3" 117 | dependencies = [ 118 | "byteorder", 119 | ] 120 | 121 | [[package]] 122 | name = "byteorder" 123 | version = "0.3.13" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "29b2aa490a8f546381308d68fc79e6bd753cd3ad839f7a7172897f1feedfa175" 126 | 127 | [[package]] 128 | name = "bytes" 129 | version = "1.1.0" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 132 | 133 | [[package]] 134 | name = "cc" 135 | version = "1.0.72" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" 138 | 139 | [[package]] 140 | name = "cexpr" 141 | version = "0.4.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" 144 | dependencies = [ 145 | "nom", 146 | ] 147 | 148 | [[package]] 149 | name = "cfg-if" 150 | version = "0.1.10" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 153 | 154 | [[package]] 155 | name = "cfg-if" 156 | version = "1.0.0" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 159 | 160 | [[package]] 161 | name = "chrono" 162 | version = "0.4.19" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 165 | dependencies = [ 166 | "libc", 167 | "num-integer", 168 | "num-traits", 169 | "time", 170 | "winapi", 171 | ] 172 | 173 | [[package]] 174 | name = "clang-sys" 175 | version = "0.29.3" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" 178 | dependencies = [ 179 | "glob", 180 | "libc", 181 | "libloading", 182 | ] 183 | 184 | [[package]] 185 | name = "clap" 186 | version = "2.34.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" 189 | dependencies = [ 190 | "ansi_term", 191 | "atty", 192 | "bitflags", 193 | "strsim", 194 | "textwrap", 195 | "unicode-width", 196 | "vec_map", 197 | ] 198 | 199 | [[package]] 200 | name = "core-foundation" 201 | version = "0.9.2" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" 204 | dependencies = [ 205 | "core-foundation-sys", 206 | "libc", 207 | ] 208 | 209 | [[package]] 210 | name = "core-foundation-sys" 211 | version = "0.8.3" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 214 | 215 | [[package]] 216 | name = "either" 217 | version = "1.6.1" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 220 | 221 | [[package]] 222 | name = "embed-resource" 223 | version = "1.6.5" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "85505eb239fc952b300f29f0556d2d884082a83566768d980278d8faf38c780d" 226 | dependencies = [ 227 | "cc", 228 | "vswhom", 229 | "winreg 0.10.1", 230 | ] 231 | 232 | [[package]] 233 | name = "encoding_rs" 234 | version = "0.8.30" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" 237 | dependencies = [ 238 | "cfg-if 1.0.0", 239 | ] 240 | 241 | [[package]] 242 | name = "env_logger" 243 | version = "0.7.1" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" 246 | dependencies = [ 247 | "atty", 248 | "humantime", 249 | "log", 250 | "regex", 251 | "termcolor", 252 | ] 253 | 254 | [[package]] 255 | name = "failure" 256 | version = "0.1.8" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" 259 | dependencies = [ 260 | "backtrace", 261 | "failure_derive", 262 | ] 263 | 264 | [[package]] 265 | name = "failure_derive" 266 | version = "0.1.8" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" 269 | dependencies = [ 270 | "proc-macro2", 271 | "quote", 272 | "syn", 273 | "synstructure", 274 | ] 275 | 276 | [[package]] 277 | name = "fnv" 278 | version = "1.0.7" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 281 | 282 | [[package]] 283 | name = "foreign-types" 284 | version = "0.3.2" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 287 | dependencies = [ 288 | "foreign-types-shared", 289 | ] 290 | 291 | [[package]] 292 | name = "foreign-types-shared" 293 | version = "0.1.1" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 296 | 297 | [[package]] 298 | name = "form_urlencoded" 299 | version = "1.0.1" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 302 | dependencies = [ 303 | "matches", 304 | "percent-encoding", 305 | ] 306 | 307 | [[package]] 308 | name = "futures" 309 | version = "0.3.18" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" 312 | dependencies = [ 313 | "futures-channel", 314 | "futures-core", 315 | "futures-executor", 316 | "futures-io", 317 | "futures-sink", 318 | "futures-task", 319 | "futures-util", 320 | ] 321 | 322 | [[package]] 323 | name = "futures-channel" 324 | version = "0.3.18" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" 327 | dependencies = [ 328 | "futures-core", 329 | "futures-sink", 330 | ] 331 | 332 | [[package]] 333 | name = "futures-core" 334 | version = "0.3.18" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" 337 | 338 | [[package]] 339 | name = "futures-executor" 340 | version = "0.3.18" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" 343 | dependencies = [ 344 | "futures-core", 345 | "futures-task", 346 | "futures-util", 347 | ] 348 | 349 | [[package]] 350 | name = "futures-io" 351 | version = "0.3.18" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" 354 | 355 | [[package]] 356 | name = "futures-macro" 357 | version = "0.3.18" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" 360 | dependencies = [ 361 | "proc-macro2", 362 | "quote", 363 | "syn", 364 | ] 365 | 366 | [[package]] 367 | name = "futures-sink" 368 | version = "0.3.18" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" 371 | 372 | [[package]] 373 | name = "futures-task" 374 | version = "0.3.18" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" 377 | 378 | [[package]] 379 | name = "futures-util" 380 | version = "0.3.18" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" 383 | dependencies = [ 384 | "futures-channel", 385 | "futures-core", 386 | "futures-io", 387 | "futures-macro", 388 | "futures-sink", 389 | "futures-task", 390 | "memchr", 391 | "pin-project-lite", 392 | "pin-utils", 393 | "slab", 394 | ] 395 | 396 | [[package]] 397 | name = "getrandom" 398 | version = "0.2.3" 399 | source = "registry+https://github.com/rust-lang/crates.io-index" 400 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 401 | dependencies = [ 402 | "cfg-if 1.0.0", 403 | "libc", 404 | "wasi", 405 | ] 406 | 407 | [[package]] 408 | name = "gimli" 409 | version = "0.26.1" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" 412 | 413 | [[package]] 414 | name = "glob" 415 | version = "0.3.0" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 418 | 419 | [[package]] 420 | name = "h2" 421 | version = "0.3.9" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" 424 | dependencies = [ 425 | "bytes", 426 | "fnv", 427 | "futures-core", 428 | "futures-sink", 429 | "futures-util", 430 | "http", 431 | "indexmap", 432 | "slab", 433 | "tokio", 434 | "tokio-util", 435 | "tracing", 436 | ] 437 | 438 | [[package]] 439 | name = "hashbrown" 440 | version = "0.11.2" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 443 | 444 | [[package]] 445 | name = "hermit-abi" 446 | version = "0.1.19" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 449 | dependencies = [ 450 | "libc", 451 | ] 452 | 453 | [[package]] 454 | name = "http" 455 | version = "0.2.5" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" 458 | dependencies = [ 459 | "bytes", 460 | "fnv", 461 | "itoa", 462 | ] 463 | 464 | [[package]] 465 | name = "http-body" 466 | version = "0.4.4" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" 469 | dependencies = [ 470 | "bytes", 471 | "http", 472 | "pin-project-lite", 473 | ] 474 | 475 | [[package]] 476 | name = "httparse" 477 | version = "1.5.1" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" 480 | 481 | [[package]] 482 | name = "httpdate" 483 | version = "1.0.2" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 486 | 487 | [[package]] 488 | name = "humantime" 489 | version = "1.3.0" 490 | source = "registry+https://github.com/rust-lang/crates.io-index" 491 | checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" 492 | dependencies = [ 493 | "quick-error", 494 | ] 495 | 496 | [[package]] 497 | name = "hyper" 498 | version = "0.14.16" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" 501 | dependencies = [ 502 | "bytes", 503 | "futures-channel", 504 | "futures-core", 505 | "futures-util", 506 | "h2", 507 | "http", 508 | "http-body", 509 | "httparse", 510 | "httpdate", 511 | "itoa", 512 | "pin-project-lite", 513 | "socket2", 514 | "tokio", 515 | "tower-service", 516 | "tracing", 517 | "want", 518 | ] 519 | 520 | [[package]] 521 | name = "hyper-tls" 522 | version = "0.5.0" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 525 | dependencies = [ 526 | "bytes", 527 | "hyper", 528 | "native-tls", 529 | "tokio", 530 | "tokio-native-tls", 531 | ] 532 | 533 | [[package]] 534 | name = "idna" 535 | version = "0.2.3" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 538 | dependencies = [ 539 | "matches", 540 | "unicode-bidi", 541 | "unicode-normalization", 542 | ] 543 | 544 | [[package]] 545 | name = "indexmap" 546 | version = "1.7.0" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" 549 | dependencies = [ 550 | "autocfg", 551 | "hashbrown", 552 | ] 553 | 554 | [[package]] 555 | name = "instant" 556 | version = "0.1.12" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 559 | dependencies = [ 560 | "cfg-if 1.0.0", 561 | ] 562 | 563 | [[package]] 564 | name = "ipnet" 565 | version = "2.3.1" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" 568 | 569 | [[package]] 570 | name = "itoa" 571 | version = "0.4.8" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" 574 | 575 | [[package]] 576 | name = "iui" 577 | version = "0.3.0" 578 | source = "git+https://github.com/rust-native-ui/libui-rs?branch=trunk#6ff94425b341cf718e29d07067dbf82f9215a6d5" 579 | dependencies = [ 580 | "bitflags", 581 | "failure", 582 | "lazy_static", 583 | "libc", 584 | "regex", 585 | "ui-sys", 586 | ] 587 | 588 | [[package]] 589 | name = "js-sys" 590 | version = "0.3.55" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" 593 | dependencies = [ 594 | "wasm-bindgen", 595 | ] 596 | 597 | [[package]] 598 | name = "lazy_static" 599 | version = "1.4.0" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 602 | 603 | [[package]] 604 | name = "lazycell" 605 | version = "1.3.0" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 608 | 609 | [[package]] 610 | name = "libc" 611 | version = "0.2.109" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" 614 | 615 | [[package]] 616 | name = "libloading" 617 | version = "0.5.2" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" 620 | dependencies = [ 621 | "cc", 622 | "winapi", 623 | ] 624 | 625 | [[package]] 626 | name = "lock_api" 627 | version = "0.4.5" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" 630 | dependencies = [ 631 | "scopeguard", 632 | ] 633 | 634 | [[package]] 635 | name = "log" 636 | version = "0.4.14" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 639 | dependencies = [ 640 | "cfg-if 1.0.0", 641 | ] 642 | 643 | [[package]] 644 | name = "matches" 645 | version = "0.1.9" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 648 | 649 | [[package]] 650 | name = "memchr" 651 | version = "2.4.1" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 654 | 655 | [[package]] 656 | name = "mime" 657 | version = "0.3.16" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 660 | 661 | [[package]] 662 | name = "miniz_oxide" 663 | version = "0.4.4" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 666 | dependencies = [ 667 | "adler", 668 | "autocfg", 669 | ] 670 | 671 | [[package]] 672 | name = "mio" 673 | version = "0.7.14" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" 676 | dependencies = [ 677 | "libc", 678 | "log", 679 | "miow", 680 | "ntapi", 681 | "winapi", 682 | ] 683 | 684 | [[package]] 685 | name = "miow" 686 | version = "0.3.7" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 689 | dependencies = [ 690 | "winapi", 691 | ] 692 | 693 | [[package]] 694 | name = "native-tls" 695 | version = "0.2.8" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" 698 | dependencies = [ 699 | "lazy_static", 700 | "libc", 701 | "log", 702 | "openssl", 703 | "openssl-probe", 704 | "openssl-sys", 705 | "schannel", 706 | "security-framework", 707 | "security-framework-sys", 708 | "tempfile", 709 | ] 710 | 711 | [[package]] 712 | name = "nom" 713 | version = "5.1.2" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 716 | dependencies = [ 717 | "memchr", 718 | "version_check", 719 | ] 720 | 721 | [[package]] 722 | name = "ntapi" 723 | version = "0.3.6" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 726 | dependencies = [ 727 | "winapi", 728 | ] 729 | 730 | [[package]] 731 | name = "num-integer" 732 | version = "0.1.44" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 735 | dependencies = [ 736 | "autocfg", 737 | "num-traits", 738 | ] 739 | 740 | [[package]] 741 | name = "num-traits" 742 | version = "0.2.14" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 745 | dependencies = [ 746 | "autocfg", 747 | ] 748 | 749 | [[package]] 750 | name = "num_cpus" 751 | version = "1.13.0" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 754 | dependencies = [ 755 | "hermit-abi", 756 | "libc", 757 | ] 758 | 759 | [[package]] 760 | name = "object" 761 | version = "0.27.1" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" 764 | dependencies = [ 765 | "memchr", 766 | ] 767 | 768 | [[package]] 769 | name = "once_cell" 770 | version = "1.8.0" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 773 | 774 | [[package]] 775 | name = "openssl" 776 | version = "0.10.38" 777 | source = "registry+https://github.com/rust-lang/crates.io-index" 778 | checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" 779 | dependencies = [ 780 | "bitflags", 781 | "cfg-if 1.0.0", 782 | "foreign-types", 783 | "libc", 784 | "once_cell", 785 | "openssl-sys", 786 | ] 787 | 788 | [[package]] 789 | name = "openssl-probe" 790 | version = "0.1.4" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" 793 | 794 | [[package]] 795 | name = "openssl-sys" 796 | version = "0.9.71" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73" 799 | dependencies = [ 800 | "autocfg", 801 | "cc", 802 | "libc", 803 | "pkg-config", 804 | "vcpkg", 805 | ] 806 | 807 | [[package]] 808 | name = "parking_lot" 809 | version = "0.11.2" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 812 | dependencies = [ 813 | "instant", 814 | "lock_api", 815 | "parking_lot_core", 816 | ] 817 | 818 | [[package]] 819 | name = "parking_lot_core" 820 | version = "0.8.5" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 823 | dependencies = [ 824 | "cfg-if 1.0.0", 825 | "instant", 826 | "libc", 827 | "redox_syscall", 828 | "smallvec", 829 | "winapi", 830 | ] 831 | 832 | [[package]] 833 | name = "peeking_take_while" 834 | version = "0.1.2" 835 | source = "registry+https://github.com/rust-lang/crates.io-index" 836 | checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" 837 | 838 | [[package]] 839 | name = "percent-encoding" 840 | version = "2.1.0" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 843 | 844 | [[package]] 845 | name = "pin-project-lite" 846 | version = "0.2.7" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" 849 | 850 | [[package]] 851 | name = "pin-utils" 852 | version = "0.1.0" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 855 | 856 | [[package]] 857 | name = "pkg-config" 858 | version = "0.3.24" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" 861 | 862 | [[package]] 863 | name = "ppv-lite86" 864 | version = "0.2.15" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" 867 | 868 | [[package]] 869 | name = "proc-macro2" 870 | version = "1.0.33" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a" 873 | dependencies = [ 874 | "unicode-xid", 875 | ] 876 | 877 | [[package]] 878 | name = "quick-error" 879 | version = "1.2.3" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 882 | 883 | [[package]] 884 | name = "quote" 885 | version = "1.0.10" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" 888 | dependencies = [ 889 | "proc-macro2", 890 | ] 891 | 892 | [[package]] 893 | name = "rand" 894 | version = "0.8.4" 895 | source = "registry+https://github.com/rust-lang/crates.io-index" 896 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 897 | dependencies = [ 898 | "libc", 899 | "rand_chacha", 900 | "rand_core", 901 | "rand_hc", 902 | ] 903 | 904 | [[package]] 905 | name = "rand_chacha" 906 | version = "0.3.1" 907 | source = "registry+https://github.com/rust-lang/crates.io-index" 908 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 909 | dependencies = [ 910 | "ppv-lite86", 911 | "rand_core", 912 | ] 913 | 914 | [[package]] 915 | name = "rand_core" 916 | version = "0.6.3" 917 | source = "registry+https://github.com/rust-lang/crates.io-index" 918 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 919 | dependencies = [ 920 | "getrandom", 921 | ] 922 | 923 | [[package]] 924 | name = "rand_hc" 925 | version = "0.3.1" 926 | source = "registry+https://github.com/rust-lang/crates.io-index" 927 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 928 | dependencies = [ 929 | "rand_core", 930 | ] 931 | 932 | [[package]] 933 | name = "redox_syscall" 934 | version = "0.2.10" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" 937 | dependencies = [ 938 | "bitflags", 939 | ] 940 | 941 | [[package]] 942 | name = "regex" 943 | version = "1.5.4" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 946 | dependencies = [ 947 | "aho-corasick", 948 | "memchr", 949 | "regex-syntax", 950 | ] 951 | 952 | [[package]] 953 | name = "regex-syntax" 954 | version = "0.6.25" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 957 | 958 | [[package]] 959 | name = "remove_dir_all" 960 | version = "0.5.3" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 963 | dependencies = [ 964 | "winapi", 965 | ] 966 | 967 | [[package]] 968 | name = "reqwest" 969 | version = "0.11.7" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "07bea77bc708afa10e59905c3d4af7c8fd43c9214251673095ff8b14345fcbc5" 972 | dependencies = [ 973 | "base64", 974 | "bytes", 975 | "encoding_rs", 976 | "futures-core", 977 | "futures-util", 978 | "http", 979 | "http-body", 980 | "hyper", 981 | "hyper-tls", 982 | "ipnet", 983 | "js-sys", 984 | "lazy_static", 985 | "log", 986 | "mime", 987 | "native-tls", 988 | "percent-encoding", 989 | "pin-project-lite", 990 | "serde", 991 | "serde_json", 992 | "serde_urlencoded", 993 | "tokio", 994 | "tokio-native-tls", 995 | "tokio-socks", 996 | "url", 997 | "wasm-bindgen", 998 | "wasm-bindgen-futures", 999 | "web-sys", 1000 | "winreg 0.7.0", 1001 | ] 1002 | 1003 | [[package]] 1004 | name = "rustc-demangle" 1005 | version = "0.1.21" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" 1008 | 1009 | [[package]] 1010 | name = "rustc-hash" 1011 | version = "1.1.0" 1012 | source = "registry+https://github.com/rust-lang/crates.io-index" 1013 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 1014 | 1015 | [[package]] 1016 | name = "ryu" 1017 | version = "1.0.7" 1018 | source = "registry+https://github.com/rust-lang/crates.io-index" 1019 | checksum = "254df5081ce98661a883445175e52efe99d1cb2a5552891d965d2f5d0cad1c16" 1020 | 1021 | [[package]] 1022 | name = "schannel" 1023 | version = "0.1.19" 1024 | source = "registry+https://github.com/rust-lang/crates.io-index" 1025 | checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" 1026 | dependencies = [ 1027 | "lazy_static", 1028 | "winapi", 1029 | ] 1030 | 1031 | [[package]] 1032 | name = "scopeguard" 1033 | version = "1.1.0" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1036 | 1037 | [[package]] 1038 | name = "security-framework" 1039 | version = "2.4.2" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" 1042 | dependencies = [ 1043 | "bitflags", 1044 | "core-foundation", 1045 | "core-foundation-sys", 1046 | "libc", 1047 | "security-framework-sys", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "security-framework-sys" 1052 | version = "2.4.2" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" 1055 | dependencies = [ 1056 | "core-foundation-sys", 1057 | "libc", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "serde" 1062 | version = "1.0.131" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" 1065 | 1066 | [[package]] 1067 | name = "serde_json" 1068 | version = "1.0.72" 1069 | source = "registry+https://github.com/rust-lang/crates.io-index" 1070 | checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" 1071 | dependencies = [ 1072 | "itoa", 1073 | "ryu", 1074 | "serde", 1075 | ] 1076 | 1077 | [[package]] 1078 | name = "serde_urlencoded" 1079 | version = "0.7.0" 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" 1081 | checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" 1082 | dependencies = [ 1083 | "form_urlencoded", 1084 | "itoa", 1085 | "ryu", 1086 | "serde", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "shlex" 1091 | version = "0.1.1" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" 1094 | 1095 | [[package]] 1096 | name = "signal-hook-registry" 1097 | version = "1.4.0" 1098 | source = "registry+https://github.com/rust-lang/crates.io-index" 1099 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1100 | dependencies = [ 1101 | "libc", 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "slab" 1106 | version = "0.4.5" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" 1109 | 1110 | [[package]] 1111 | name = "smallvec" 1112 | version = "1.7.0" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" 1115 | 1116 | [[package]] 1117 | name = "socket2" 1118 | version = "0.4.2" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" 1121 | dependencies = [ 1122 | "libc", 1123 | "winapi", 1124 | ] 1125 | 1126 | [[package]] 1127 | name = "strsim" 1128 | version = "0.8.0" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 1131 | 1132 | [[package]] 1133 | name = "syn" 1134 | version = "1.0.82" 1135 | source = "registry+https://github.com/rust-lang/crates.io-index" 1136 | checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" 1137 | dependencies = [ 1138 | "proc-macro2", 1139 | "quote", 1140 | "unicode-xid", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "synstructure" 1145 | version = "0.12.6" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" 1148 | dependencies = [ 1149 | "proc-macro2", 1150 | "quote", 1151 | "syn", 1152 | "unicode-xid", 1153 | ] 1154 | 1155 | [[package]] 1156 | name = "tempfile" 1157 | version = "3.2.0" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" 1160 | dependencies = [ 1161 | "cfg-if 1.0.0", 1162 | "libc", 1163 | "rand", 1164 | "redox_syscall", 1165 | "remove_dir_all", 1166 | "winapi", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "termcolor" 1171 | version = "1.1.2" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 1174 | dependencies = [ 1175 | "winapi-util", 1176 | ] 1177 | 1178 | [[package]] 1179 | name = "textwrap" 1180 | version = "0.11.0" 1181 | source = "registry+https://github.com/rust-lang/crates.io-index" 1182 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 1183 | dependencies = [ 1184 | "unicode-width", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "thiserror" 1189 | version = "1.0.30" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 1192 | dependencies = [ 1193 | "thiserror-impl", 1194 | ] 1195 | 1196 | [[package]] 1197 | name = "thiserror-impl" 1198 | version = "1.0.30" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 1201 | dependencies = [ 1202 | "proc-macro2", 1203 | "quote", 1204 | "syn", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "time" 1209 | version = "0.1.43" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 1212 | dependencies = [ 1213 | "libc", 1214 | "winapi", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "tinyvec" 1219 | version = "1.5.1" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" 1222 | dependencies = [ 1223 | "tinyvec_macros", 1224 | ] 1225 | 1226 | [[package]] 1227 | name = "tinyvec_macros" 1228 | version = "0.1.0" 1229 | source = "registry+https://github.com/rust-lang/crates.io-index" 1230 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1231 | 1232 | [[package]] 1233 | name = "tokio" 1234 | version = "1.14.0" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" 1237 | dependencies = [ 1238 | "autocfg", 1239 | "bytes", 1240 | "libc", 1241 | "memchr", 1242 | "mio", 1243 | "num_cpus", 1244 | "once_cell", 1245 | "parking_lot", 1246 | "pin-project-lite", 1247 | "signal-hook-registry", 1248 | "tokio-macros", 1249 | "winapi", 1250 | ] 1251 | 1252 | [[package]] 1253 | name = "tokio-macros" 1254 | version = "1.6.0" 1255 | source = "registry+https://github.com/rust-lang/crates.io-index" 1256 | checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" 1257 | dependencies = [ 1258 | "proc-macro2", 1259 | "quote", 1260 | "syn", 1261 | ] 1262 | 1263 | [[package]] 1264 | name = "tokio-native-tls" 1265 | version = "0.3.0" 1266 | source = "registry+https://github.com/rust-lang/crates.io-index" 1267 | checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" 1268 | dependencies = [ 1269 | "native-tls", 1270 | "tokio", 1271 | ] 1272 | 1273 | [[package]] 1274 | name = "tokio-socks" 1275 | version = "0.5.1" 1276 | source = "registry+https://github.com/rust-lang/crates.io-index" 1277 | checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" 1278 | dependencies = [ 1279 | "either", 1280 | "futures-util", 1281 | "thiserror", 1282 | "tokio", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "tokio-util" 1287 | version = "0.6.9" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" 1290 | dependencies = [ 1291 | "bytes", 1292 | "futures-core", 1293 | "futures-sink", 1294 | "log", 1295 | "pin-project-lite", 1296 | "tokio", 1297 | ] 1298 | 1299 | [[package]] 1300 | name = "tower-service" 1301 | version = "0.3.1" 1302 | source = "registry+https://github.com/rust-lang/crates.io-index" 1303 | checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" 1304 | 1305 | [[package]] 1306 | name = "tracing" 1307 | version = "0.1.29" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" 1310 | dependencies = [ 1311 | "cfg-if 1.0.0", 1312 | "pin-project-lite", 1313 | "tracing-core", 1314 | ] 1315 | 1316 | [[package]] 1317 | name = "tracing-core" 1318 | version = "0.1.21" 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" 1320 | checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" 1321 | dependencies = [ 1322 | "lazy_static", 1323 | ] 1324 | 1325 | [[package]] 1326 | name = "treasurehole" 1327 | version = "0.1.0" 1328 | dependencies = [ 1329 | "bytebuffer", 1330 | "bytes", 1331 | "chrono", 1332 | "futures", 1333 | "iui", 1334 | "regex", 1335 | "reqwest", 1336 | "serde_json", 1337 | "tokio", 1338 | ] 1339 | 1340 | [[package]] 1341 | name = "try-lock" 1342 | version = "0.2.3" 1343 | source = "registry+https://github.com/rust-lang/crates.io-index" 1344 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 1345 | 1346 | [[package]] 1347 | name = "ui-sys" 1348 | version = "0.2.1" 1349 | source = "git+https://github.com/rust-native-ui/libui-rs?branch=trunk#6ff94425b341cf718e29d07067dbf82f9215a6d5" 1350 | dependencies = [ 1351 | "bindgen", 1352 | "cc", 1353 | "embed-resource", 1354 | "libc", 1355 | "pkg-config", 1356 | ] 1357 | 1358 | [[package]] 1359 | name = "unicode-bidi" 1360 | version = "0.3.7" 1361 | source = "registry+https://github.com/rust-lang/crates.io-index" 1362 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" 1363 | 1364 | [[package]] 1365 | name = "unicode-normalization" 1366 | version = "0.1.19" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 1369 | dependencies = [ 1370 | "tinyvec", 1371 | ] 1372 | 1373 | [[package]] 1374 | name = "unicode-width" 1375 | version = "0.1.9" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" 1378 | 1379 | [[package]] 1380 | name = "unicode-xid" 1381 | version = "0.2.2" 1382 | source = "registry+https://github.com/rust-lang/crates.io-index" 1383 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 1384 | 1385 | [[package]] 1386 | name = "url" 1387 | version = "2.2.2" 1388 | source = "registry+https://github.com/rust-lang/crates.io-index" 1389 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 1390 | dependencies = [ 1391 | "form_urlencoded", 1392 | "idna", 1393 | "matches", 1394 | "percent-encoding", 1395 | ] 1396 | 1397 | [[package]] 1398 | name = "vcpkg" 1399 | version = "0.2.15" 1400 | source = "registry+https://github.com/rust-lang/crates.io-index" 1401 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1402 | 1403 | [[package]] 1404 | name = "vec_map" 1405 | version = "0.8.2" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 1408 | 1409 | [[package]] 1410 | name = "version_check" 1411 | version = "0.9.3" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 1414 | 1415 | [[package]] 1416 | name = "vswhom" 1417 | version = "0.1.0" 1418 | source = "registry+https://github.com/rust-lang/crates.io-index" 1419 | checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" 1420 | dependencies = [ 1421 | "libc", 1422 | "vswhom-sys", 1423 | ] 1424 | 1425 | [[package]] 1426 | name = "vswhom-sys" 1427 | version = "0.1.0" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "fc2f5402d3d0e79a069714f7b48e3ecc60be7775a2c049cb839457457a239532" 1430 | dependencies = [ 1431 | "cc", 1432 | "libc", 1433 | ] 1434 | 1435 | [[package]] 1436 | name = "want" 1437 | version = "0.3.0" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 1440 | dependencies = [ 1441 | "log", 1442 | "try-lock", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "wasi" 1447 | version = "0.10.2+wasi-snapshot-preview1" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 1450 | 1451 | [[package]] 1452 | name = "wasm-bindgen" 1453 | version = "0.2.78" 1454 | source = "registry+https://github.com/rust-lang/crates.io-index" 1455 | checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" 1456 | dependencies = [ 1457 | "cfg-if 1.0.0", 1458 | "wasm-bindgen-macro", 1459 | ] 1460 | 1461 | [[package]] 1462 | name = "wasm-bindgen-backend" 1463 | version = "0.2.78" 1464 | source = "registry+https://github.com/rust-lang/crates.io-index" 1465 | checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" 1466 | dependencies = [ 1467 | "bumpalo", 1468 | "lazy_static", 1469 | "log", 1470 | "proc-macro2", 1471 | "quote", 1472 | "syn", 1473 | "wasm-bindgen-shared", 1474 | ] 1475 | 1476 | [[package]] 1477 | name = "wasm-bindgen-futures" 1478 | version = "0.4.28" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" 1481 | dependencies = [ 1482 | "cfg-if 1.0.0", 1483 | "js-sys", 1484 | "wasm-bindgen", 1485 | "web-sys", 1486 | ] 1487 | 1488 | [[package]] 1489 | name = "wasm-bindgen-macro" 1490 | version = "0.2.78" 1491 | source = "registry+https://github.com/rust-lang/crates.io-index" 1492 | checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" 1493 | dependencies = [ 1494 | "quote", 1495 | "wasm-bindgen-macro-support", 1496 | ] 1497 | 1498 | [[package]] 1499 | name = "wasm-bindgen-macro-support" 1500 | version = "0.2.78" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" 1503 | dependencies = [ 1504 | "proc-macro2", 1505 | "quote", 1506 | "syn", 1507 | "wasm-bindgen-backend", 1508 | "wasm-bindgen-shared", 1509 | ] 1510 | 1511 | [[package]] 1512 | name = "wasm-bindgen-shared" 1513 | version = "0.2.78" 1514 | source = "registry+https://github.com/rust-lang/crates.io-index" 1515 | checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" 1516 | 1517 | [[package]] 1518 | name = "web-sys" 1519 | version = "0.3.55" 1520 | source = "registry+https://github.com/rust-lang/crates.io-index" 1521 | checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" 1522 | dependencies = [ 1523 | "js-sys", 1524 | "wasm-bindgen", 1525 | ] 1526 | 1527 | [[package]] 1528 | name = "which" 1529 | version = "3.1.1" 1530 | source = "registry+https://github.com/rust-lang/crates.io-index" 1531 | checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" 1532 | dependencies = [ 1533 | "libc", 1534 | ] 1535 | 1536 | [[package]] 1537 | name = "winapi" 1538 | version = "0.3.9" 1539 | source = "registry+https://github.com/rust-lang/crates.io-index" 1540 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1541 | dependencies = [ 1542 | "winapi-i686-pc-windows-gnu", 1543 | "winapi-x86_64-pc-windows-gnu", 1544 | ] 1545 | 1546 | [[package]] 1547 | name = "winapi-i686-pc-windows-gnu" 1548 | version = "0.4.0" 1549 | source = "registry+https://github.com/rust-lang/crates.io-index" 1550 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1551 | 1552 | [[package]] 1553 | name = "winapi-util" 1554 | version = "0.1.5" 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" 1556 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1557 | dependencies = [ 1558 | "winapi", 1559 | ] 1560 | 1561 | [[package]] 1562 | name = "winapi-x86_64-pc-windows-gnu" 1563 | version = "0.4.0" 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" 1565 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1566 | 1567 | [[package]] 1568 | name = "winreg" 1569 | version = "0.7.0" 1570 | source = "registry+https://github.com/rust-lang/crates.io-index" 1571 | checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" 1572 | dependencies = [ 1573 | "winapi", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "winreg" 1578 | version = "0.10.1" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 1581 | dependencies = [ 1582 | "winapi", 1583 | ] 1584 | --------------------------------------------------------------------------------