VchentozV

VchentozV

V2EX 第 547838 号会员,加入于 2021-06-09 10:54:49 +08:00
今日活跃度排名 9924
根据 VchentozV 的设置,主题列表被隐藏
二手交易 相关的信息,包括已关闭的交易,不会被隐藏
VchentozV 最近回复了
1 天前
回复了 PeiXyJ 创建的主题 生活 这些年传染病也太多了吧...
@FightPig 作为一个很少生病的人, 这次的症状明显就不是普通的 受寒/病毒感冒, 持续时间长, 症状和新冠一样

至于为什么不宣传新冠了? 不是说老美年年各种流感当作小感冒, 小意思啦
1 天前
回复了 PTLin 创建的主题 程序员 火星了,原来 Windows 也有了原生 sudo 了
@x009ba1 微软的 powershell 号称第 4 代, 但是和 wpf 一样, 又臭又长
钱不是白花的
1 天前
回复了 PeiXyJ 创建的主题 生活 这些年传染病也太多了吧...
前一段时间不是免签, 老外入境游
1 天前
回复了 tuoniaoguoce 创建的主题 Android 开源的 4K 壁纸软件有哪些?
纯 ai 生成, 微调了一下
1 天前
回复了 tuoniaoguoce 创建的主题 Android 开源的 4K 壁纸软件有哪些?
自己去搞一个 access_key
1 天前
回复了 tuoniaoguoce 创建的主题 Android 开源的 4K 壁纸软件有哪些?
import axios from 'axios';
import fs from 'fs';
import path from 'path';
import os from 'os';
import crypto from 'crypto';
import { setWallpaper } from 'wallpaper';
import readline from 'readline';
import { SocksProxyAgent } from 'socks-proxy-agent';

const UNSPLASH_API_URL = 'https://api.unsplash.com/photos/random';
const ACCESS_KEY = 'Z_GQ0Jd3V27mew6lRc1MB-1ojS0e9s9W7B5FPN6XoZc'; // Replace with your Unsplash access key
const INTERVAL = 5 * 60 * 1000; // 5 minutes
const DOWNLOAD_TIMEOUT = 60 * 1000; // 1 minute
const THREAD_COUNT = 4; // Number of threads for parallel download
const RETRY_LIMIT = 3; // Retry limit for failed downloads
const PROGRESS_TIMEOUT = 10 * 1000; // 10 seconds timeout for progress check
const MIN_SPEED = 10; // Minimum speed in KB/s to consider as stalled

// SOCKS5 Proxy setup
const proxyUrl = 'socks5h://127.0.0.1:1080'; // Replace with your SOCKS5 proxy server address and port
const agent = new SocksProxyAgent(proxyUrl);

// Keywords list
const originalKeywords = [
'mountain', 'africa', 'middle east', 'snow', 'travel',
'Caribbean', 'Hubble Space Telescope', 'roman',
'Soviets', 'Aegean Sea',
'Bahrain', 'Eritrea', 'Iran', 'Iraq', 'Israel',
'Jordan', 'Kuwait', 'Lebanon', 'Oman', 'Qatar',
'Saudi Arabia', 'Syria', 'United Arab Emirates', 'Yemen',
// Europe
'Albania', 'Andorra', 'Austria', 'Belarus', 'Belgium',
'Bosnia and Herzegovina', 'Bulgaria', 'Iceland', 'Ireland',
'Italy', 'Kosovo', 'Latvia', 'Lithuania', 'Luxembourg',
'Malta', 'Monaco', 'Moldova', 'Norway', 'Netherlands',
'Portugal', 'Romania', 'Russia', 'San Marino', 'Serbia',
'Cyprus', 'Slovakia', 'Slovenia', 'Spain', 'Switzerland',
'Ukraine', 'United Kingdom', 'Vatican City',
// Asia
'Afghanistan', 'United Arab Emirates', 'Armenia', 'China',
'Georgia', 'India', 'Indonesia', 'Iran', 'Iraq',
'Israel', 'Japan', 'Jordan', 'Kazakhstan', 'South Korea',
'Kuwait', 'Kyrgyzstan', 'Lebanon', 'Maldives', 'Mongolia',
'Myanmar', 'Nepal', 'Macau', 'Malaysia', 'Pakistan',
'Philippines', 'Russia', 'Saudi Arabia', 'Singapore',
'Sri Lanka', 'Syria', 'Tajikistan', 'Thailand', 'Timor-Leste',
'Turkey', 'Turkmenistan', 'Uzbekistan', 'Yemen',
// Caribbean and South America
'Antigua and Barbuda', 'Bahamas', 'Barbados', 'Bolivia',
'Colombia', 'Cuba', 'Dominica', 'Dominican Republic',
'Grenada', 'Guyana', 'Haiti', 'Honduras', 'Jamaica',
'Nicaragua', 'Paraguay', 'Peru', 'Saint Kitts and Nevis',
'Saint Lucia', 'Saint Vincent and the Grenadines', 'Suriname',
'Trinidad and Tobago', 'Venezuela'
];

// Create a copy of the original keywords to keep track of unused ones
let unusedKeywords = [...originalKeywords];

// Function to generate a random hash
function generateHash(length = 8) {
return crypto.randomBytes(length).toString('hex');
}

// Function to get the path for temporary file
function getTempFilePath(partIndex) {
const tempDir = os.tmpdir();
return path.join(tempDir, `wallpaper_part${partIndex}.tmp`);
}

// Function to get a random keyword
function getRandomKeyword() {
if (unusedKeywords.length === 0) {
unusedKeywords = [...originalKeywords]; // Reset the list when all keywords have been used
console.log('All keywords used, resetting keyword list.');
}
const randomIndex = Math.floor(Math.random() * unusedKeywords.length);
const keyword = unusedKeywords[randomIndex];
unusedKeywords.splice(randomIndex, 1); // Remove the keyword from the list
return keyword;
}

async function downloadPart(photoUrl, start, end, partIndex, totalLength, downloadedParts, startTime) {
let retryCount = 0;
let lastProgress = 0;
let progressTimer;
const tempFilePath = getTempFilePath(partIndex);

// Read previous progress
if (fs.existsSync(tempFilePath)) {
downloadedParts[partIndex] = fs.statSync(tempFilePath).size;
}

while (retryCount < RETRY_LIMIT) {
try {
let currentStart = start + downloadedParts[partIndex];

const response = await axios.get(photoUrl, {
headers: {
'Range': `bytes=${currentStart}-${end}`,
},
responseType: 'arraybuffer',
httpAgent: agent, // Apply the SOCKS5 agent
httpsAgent: agent, // Apply the SOCKS5 agent
onDownloadProgress: (progressEvent) => {
const newBytes = progressEvent.loaded - downloadedParts[partIndex];
downloadedParts[partIndex] += newBytes;
updateProgress(downloadedParts, totalLength, startTime);

const elapsedTime = (Date.now() - startTime) / 1000; // in seconds
const speed = (newBytes / 1024 / elapsedTime).toFixed(2); // in KB/s

// Reset progress timer on new data
clearTimeout(progressTimer);
progressTimer = setTimeout(() => {
if (downloadedParts[partIndex] <= lastProgress || speed < MIN_SPEED) {
console.log(`\nPart ${partIndex + 1} is stalled or too slow, retrying...`);
retryCount++;
if (retryCount >= RETRY_LIMIT) {
throw new Error(`Failed to download part ${partIndex + 1} after ${RETRY_LIMIT} attempts.`);
}
lastProgress = downloadedParts[partIndex];
downloadPart(photoUrl, start, end, partIndex, totalLength, downloadedParts, startTime);
}
}, PROGRESS_TIMEOUT);
}
});

// Append data to temp file
fs.writeFileSync(tempFilePath, response.data, { flag: 'a' });
clearTimeout(progressTimer);
break; // Exit the loop if download was successful

} catch (error) {
console.error(`Part ${partIndex + 1} failed, retrying... (${retryCount}/${RETRY_LIMIT})`);
if (retryCount >= RETRY_LIMIT) {
throw new Error(`Failed to download part ${partIndex + 1} after ${RETRY_LIMIT} attempts.`);
}
}
}
}

async function downloadRandomPhoto() {
console.log('Attempting to download a new wallpaper...');

try {
const keyword = getRandomKeyword(); // Select a random keyword
console.log(`Using keyword: ${keyword}`);

const response = await axios.get(UNSPLASH_API_URL, {
headers: { Authorization: `Client-ID ${ACCESS_KEY}` },
params: {
query: keyword,
},
httpAgent: agent, // Apply the SOCKS5 agent
httpsAgent: agent, // Apply the SOCKS5 agent
});

console.log('Received response from Unsplash API.');

const photoUrl = response.data.urls.full;
console.log(`Photo URL: ${photoUrl}`);

const headResponse = await axios.head(photoUrl, { httpAgent: agent, httpsAgent: agent });
const totalLength = parseInt(headResponse.headers['content-length'], 10);
const tempDir = os.tmpdir();
const hash = generateHash();
const fileName = path.join(tempDir, `wallpaper_${hash}.jpg`);
console.log(`Total size: ${totalLength} bytes`);
console.log(`Saving photo to: ${fileName}`);

const partSize = Math.ceil(totalLength / THREAD_COUNT);
const downloadedParts = new Array(THREAD_COUNT).fill(0);
let startTime = Date.now();

const promises = [];

for (let i = 0; i < THREAD_COUNT; i++) {
const start = i * partSize;
const end = Math.min(start + partSize - 1, totalLength - 1);

console.log(`Downloading part ${i + 1}: bytes ${start}-${end}`);

const promise = downloadPart(photoUrl, start, end, i, totalLength, downloadedParts, startTime);
promises.push(promise);
}

await Promise.all(promises);

// Combine all parts into a single file
const writeStream = fs.createWriteStream(fileName);
for (let i = 0; i < THREAD_COUNT; i++) {
const tempFilePath = getTempFilePath(i);
const data = fs.readFileSync(tempFilePath);
writeStream.write(data);
fs.unlinkSync(tempFilePath); // Delete part file after merging
}
writeStream.end();

console.log('\nPhoto download complete. Setting wallpaper...');

setWallpaper(fileName).then(() => {
console.log('Wallpaper updated successfully!');
}).catch(err => {
console.error('Failed to set wallpaper:', err);
});

} catch (error) {
console.error('Error in downloadRandomPhoto function:', error);
}
}

function updateProgress(downloadedParts, totalLength, startTime) {
const downloadedLength = downloadedParts.reduce((acc, val) => acc + val, 0);
const percent = ((downloadedLength / totalLength) * 100).toFixed(2);

const elapsedTime = (Date.now() - startTime) / 1000; // in seconds
const speed = (downloadedLength / 1024 / elapsedTime).toFixed(2); // in KB/s

readline.clearLine(process.stdout, 0);
readline.cursorTo(process.stdout, 0);
process.stdout.write(`Download progress: ${percent}% | Speed: ${speed} KB/s`);
}

downloadRandomPhoto();
setInterval(() => {
console.log('Starting new wallpaper update cycle...');
downloadRandomPhoto();
}, INTERVAL);
1 天前
回复了 iintothewind 创建的主题 职场话题 最近几次 Technical Interview 的复盘
国内一样啊, 面试造航母, 干活拧螺丝. 因为有造航母的能力, 所以拧螺丝大概率是不会出错的.
袁征 都当美国工程院院士了.
最后的最后,我实在看不明白什么改变命运之类的。我到了 xxx 接触了各色人等才听说这个词,还没明白啥意思。

我们家的教育从来都是
1. 做自己喜欢/适合(擅长)的事情,
2. 人要有理想,立大志做大事。
3. 你所做的事情最终要被社会认可(认可的标准是什么?嘴炮嘛?)

举院士的例子只是想说明,中国不会埋没/亏待为这个国家做过贡献的人。以前中国是穷,现在,也只是一套房子。当然,荣誉远远重于物质。我对科学家的景仰,目前仅限于老一辈的。

很多人不是想改变命运嘛? 我记得最近刷到过一个父母一聋一哑的年轻人考上清华,说要为国家造 xxx 的。
v2 上很多人肯定会笑这个人傻,但是,我可以说,只要这个人的初心不变,一定能够改变命运。

话说回来,什么叫改变命运? 成为院士和科学家?那先坐十年冷板凳。
成为老板,赢取白富美?那先学会赚钱。
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2882 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 10ms · UTC 14:31 · PVG 22:31 · LAX 06:31 · JFK 09:31
Developed with CodeLauncher
♥ Do have faith in what you're doing.