V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  VchentozV  ›  全部回复第 1 页 / 共 37 页
回复总数  732
1  2  3  4  5  6  7  8  9  10 ... 37  
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 上很多人肯定会笑这个人傻,但是,我可以说,只要这个人的初心不变,一定能够改变命运。

话说回来,什么叫改变命运? 成为院士和科学家?那先坐十年冷板凳。
成为老板,赢取白富美?那先学会赚钱。
1 天前
回复了 xiaohupro 创建的主题 React React 学习曲线要比 Vue 陡峭许多呀
再多讲一句吧,比起高技术门槛搞垄断,我个人认为这种低技术门槛的工具其实让更多的人能够多赚点钱。当然这种低技术门槛也意味着做螺丝钉容易被替换。所以妄想不学习一直赚这么多钱到老是不太现实的。
@kk2syc 哭脸
2 天前
回复了 PTLin 创建的主题 程序员 火星了,原来 Windows 也有了原生 sudo 了
@Tumblr 专业程序员用顺手还是 linux + sudo 那一套, windows 早期的设计就是傻瓜化, 就是面向普通用户, 抢市场.

所以每次 windows terminal 很多个 tab 然后突然要 win 键 + 鼠标管理员权限就很不爽.

大部分时候我就用 触摸板 点一下 + 号. 鼠标都用得不多.


===> 但是跳出程序员的局限,像父母这种用户有多少. 但是 00 后会不会动手能力都增强了?
2 天前
回复了 PTLin 创建的主题 程序员 火星了,原来 Windows 也有了原生 sudo 了
@PTLin 我现在 windows terminal 默认管理员权限. 但是最近升级了 Windows 11 24h2 之后, 就各种问题, 卡死.
2 天前
回复了 Ayaya233 创建的主题 职场话题 被 hr 疯狂催入职
你这样已经提离职了, 还有退路吗?

这个就像啥, 你有一个女朋友, 然后找了另一个...然后下一个还不靠谱...但是现在的已经知道了...
2 天前
回复了 PTLin 创建的主题 程序员 火星了,原来 Windows 也有了原生 sudo 了
不知道加这个东西有什么用
3 天前
回复了 bloodspasm 创建的主题 生活 真爱是什么样的?
张无忌为什么选赵敏?
3 天前
回复了 panchang 创建的主题 职场话题 offer 方向二选一 求 v 友们指点迷津
你要算你一个月能够剩下多少钱
3 天前
回复了 xiaohupro 创建的主题 React React 学习曲线要比 Vue 陡峭许多呀
魔法多的东西能看源码的都不是事情

反正高考筛选的就是阅读理解和应用

就是乱起八糟各种写法看起来心烦

我记得以前旧时代的微软 team 还要商量 code convention
睡了一觉,脑子清醒了,反正我是混子,搞搞自己喜欢的,我被迫开荒之后虽然觉得有成就感,但又变回了混子,搞自己喜欢的技术。
1  2  3  4  5  6  7  8  9  10 ... 37  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2731 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 29ms · UTC 15:00 · PVG 23:00 · LAX 07:00 · JFK 10:00
Developed with CodeLauncher
♥ Do have faith in what you're doing.