开始前准备:
huggingface账号:
https://huggingface.co/
**其他容器平台也可运行**
网盘账号:
https://infini-cloud.net/en/
`Dockerfile`
```
FROM node:14
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 8080
CMD [“node”, “index.js”]
```
`README.md` 最后加
```
app_port: 8080
```
`index.js`
```
const http = require('http');
const fetch = require('node-fetch');
const cron = require('node-cron');
const { createClient } = require('webdav');
const axios = require('axios');
const crypto = require('crypto');
const IMAGE_API_URL = ‘https://tuapi.eees.cc/api.php?category={dongman,fengjing,biying,meinv}&type=302’;
const PORT = process.env.PORT || 8080;
// WebDAV configuration from environment variables
const WEBDAV_BASE_URL = process.env.WEBDAV_URL;
const WEBDAV_USERNAME = process.env.WEBDAV_USERNAME;
const WEBDAV_PASSWORD = process.env.WEBDAV_PASSWORD;
if (!WEBDAV_BASE_URL || !WEBDAV_USERNAME || !WEBDAV_PASSWORD) {
console.error(‘WebDAV configuration is missing. Please set WEBDAV_URL, WEBDAV_USERNAME, and WEBDAV_PASSWORD environment variables.’);
process.exit(1);
}
const WEBDAV_API_URL = WEBDAV_BASE_URL;
const webdavClient = createClient(WEBDAV_API_URL, {
username: WEBDAV_USERNAME,
password: WEBDAV_PASSWORD,
headers: {
‘User-Agent’: ‘Node.js WebDAV Client’
},
maxBodyLength: Infinity,
maxContentLength: Infinity
});
let uploadedImages = new Set();
async function getRandomImageUrl() {
const timestamp = Date.now();
const url = ${IMAGE_API_URL}&t=${timestamp}
;
try {
const response = await fetch(url, { redirect: ‘manual’ });
return response.headers.get(‘location’);
} catch (error) {
console.error(‘Error fetching random image URL:’, error);
return null;
}
}
async function checkDirectoryPermissions(dirPath) {
try {
console.log(Checking permissions for directory: ${dirPath}
);
const exists = await webdavClient.exists(dirPath);
if (!exists) {
console.log(Directory ${dirPath} does not exist. Attempting to create...
);
await webdavClient.createDirectory(dirPath);
console.log(Directory ${dirPath} created successfully.
);
} else {
console.log(Directory ${dirPath} already exists.
);
}
// Try to create a test file
const testFilePath = `${dirPath}test_file_${Date.now()}.txt`;
await webdavClient.putFileContents(testFilePath, 'Test content');
console.log(`Test file created successfully at ${testFilePath}`);
// Delete the test file
await webdavClient.deleteFile(testFilePath);
console.log(`Test file deleted successfully.`);
return true;
} catch (error) {
console.error(Error checking directory permissions: ${error.message}
);
return false;
}
}
async function fileExistsInWebDAV(filePath) {
try {
return await webdavClient.exists(filePath);
} catch (error) {
console.error(Error checking file existence in WebDAV: ${error.message}
);
return false;
}
}
async function downloadAndUploadImage(imageUrl) {
try {
console.log(‘Downloading image from:’, imageUrl);
const response = await axios.get(imageUrl, { responseType: ‘arraybuffer’ });
const buffer = Buffer.from(response.data, ‘binary’);
// Generate a unique filename
const hash = crypto.createHash('md5').update(imageUrl).digest('hex');
const filename = `image_${hash}.jpg`;
// Ensure the directory exists and check permissions
const dirPath = '/images/';
const hasPermission = await checkDirectoryPermissions(dirPath);
if (!hasPermission) {
throw new Error('No write permission for the directory');
}
// Check if file already exists in WebDAV
const fullPath = `${dirPath}${filename}`;
const fileExists = await fileExistsInWebDAV(fullPath);
if (fileExists) {
console.log('Duplicate image detected:', fullPath);
console.log('Skipping this update.');
return null;
}
// Upload to WebDAV
console.log('Uploading file to:', fullPath);
await webdavClient.putFileContents(fullPath, buffer, { overwrite: true });
console.log('Successfully uploaded:', filename);
return `${WEBDAV_API_URL}${fullPath}`;
} catch (error) {
console.error(‘Error in downloadAndUploadImage:’, error);
return null;
}
}
async function updateImages() {
try {
const newImageUrl = await getRandomImageUrl();
if (!newImageUrl) {
console.log(‘Failed to get a valid image URL. Skipping this update.’);
return;
}
const uploadedUrl = await downloadAndUploadImage(newImageUrl);
if (uploadedUrl) {
uploadedImages.add(uploadedUrl);
console.log('New image uploaded:', uploadedUrl);
}
} catch (error) {
console.error(‘Error updating images:’, error);
}
}
function generateHtml() {
const imagesList = Array.from(uploadedImages).reverse();
return <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>随机图片链接</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } h1 { color: #333; text-align: center; } ul { list-style-type: none; padding: 0; } li { margin-bottom: 10px; } a { color: #0066cc; text-decoration: none; word-break: break-all; } a:hover { text-decoration: underline; } </style> </head> <body> <h1>随机图片链接</h1> <p>当前共有 ${imagesList.length} 个链接</p> <ul> ${imagesList.map(url =>
<li><a href=“${url}” target=“_blank”>${url}</a></li>
).join('')} </ul> </body> </html>
;
}
const server = http.createServer((req, res) => {
if (req.url === ‘/’) {
res.writeHead(200, { ‘Content-Type’: ‘text/html; charset=utf-8’ });
res.end(generateHtml());
} else {
res.writeHead(404);
res.end(‘Not Found’);
}
});
async function checkWebDAVConnection() {
try {
console.log(‘Checking WebDAV connection…’);
console.log(‘WebDAV API URL:’, WEBDAV_API_URL);
// Try to get directory contents
console.log('Trying to get root directory contents...');
const directoryContents = await webdavClient.getDirectoryContents('/');
console.log('Root directory contents:', directoryContents);
console.log('WebDAV connection successful.');
} catch (error) {
console.error(‘Error connecting to WebDAV server:’, error);
throw error;
}
}
// 主程序部分
checkWebDAVConnection()
.then(() => {
server.listen(PORT, () => {
console.log(Server running on port ${PORT}
);
});
// Initial update
updateImages();
// Update images every 10 seconds
setInterval(updateImages, 10000);
})
.catch(error => {
console.error(‘Failed to start server due to WebDAV connection error:’, error);
process.exit(1);
});
```
爬取的网站地址为:
https://tuapi.eees.cc/
类似的API接口的网站应该都是通用的,自己替换看行不行
`package.json`
</s><i> </i>{ "name": "random-image-links", "version": "1.0.0", "description": "Random image link generator and uploader", "main": "index.js", "dependencies": { "node-cron": "^3.0.0", "node-fetch": "^2.6.1", "webdav": "^4.11.2", "axios": "^0.27.2" } }<i> </i><e>
`.gitignore`
</s><i> </i>node_modules/ links.txt index.html<i> </i><e>