UNPKG

maher-tradingview-api

Version:

Tradingview instant stocks API, indicator alerts, trading bot, and more !

246 lines (212 loc) 8.25 kB
/* eslint-disable linebreak-style */ /* eslint-disable no-multi-spaces */ /* eslint-disable linebreak-style */ const express = require('express'); const path = require('path'); const TradingView = require('../main'); const axios = require('axios'); const https = require('https'); const { promisify } = require('util'); const app = express(); const PORT = process.env.PORT || 3000; // Load environment variables require('dotenv').config(); // API Keys from environment variables const API_KEYS = { ALPHAVANTAGE: process.env.ALPHAVANTAGE_API_KEY, FINNHUB: process.env.FINNHUB_API_KEY, IEX: process.env.IEX_API_KEY }; // Validate API keys if (!API_KEYS.ALPHAVANTAGE || !API_KEYS.FINNHUB || !API_KEYS.IEX) { console.warn('Warning: Some API keys are missing. Check your .env file'); } // Create a custom axios instance with longer timeout const apiClient = axios.create({ timeout: 30000, // 30 second timeout httpsAgent: new https.Agent({ keepAlive: true }) }); // Set EJS as the view engine app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); // Middleware setup app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(express.static(path.join(__dirname, 'public'))); // CORS and performance middleware app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); res.header('Cache-Control', 'public, max-age=300'); // كاش لمدة 5 دقائق next(); }); // Root route app.get('/', (req, res) => { res.render('index', { title: 'الصفحة الرئيسية' }); }); // POST route handler for /market-data app.post('/market-data', async (req, res) => { try { const { symbol, timeframe } = req.body; if (!symbol) { return res.status(400).render('error', { title: 'خطأ', message: 'يجب تحديد رمز السهم', error: {} }); } // الحصول على بيانات السوق const data = await getMarketData(symbol, timeframe || '1d'); // عرض صفحة بيانات السوق مع البيانات المجلوبة res.render('market-data-clean', { title: `بيانات السوق لـ ${symbol}`, symbol, timeframe: timeframe || '1d', data: { data } }); } catch (error) { console.error('خطأ في معالجة بيانات السوق:', error); res.render('error', { title: 'خطأ', message: 'حدث خطأ في معالجة البيانات', error: process.env.NODE_ENV === 'development' ? error : {} }); } }); // تحسين معالجة الأخطاء const errorHandler = (err, req, res, next) => { console.error('خطأ في الخادم:', err); if (res.headersSent) { return next(err); } res.status(500).render('error', { title: 'خطأ في الخادم', message: 'حدث خطأ أثناء معالجة طلبك. يرجى المحاولة مرة أخرى.', error: process.env.NODE_ENV === 'development' ? err : {} }); }; app.use(errorHandler); // التعامل مع طلبات البيانات app.get('/api/market-data/:symbol', async (req, res) => { try { const { symbol } = req.params; const { timeframe = '1d' } = req.query; // محاولة الحصول على البيانات من المصادر المختلفة const data = await getMarketData(symbol, timeframe); if (!data || !data.data || data.data.length === 0) { return res.status(404).json({ error: 'لم يتم العثور على بيانات تاريخية', symbol, timeframe }); } res.json(data); } catch (error) { console.error('خطأ في الحصول على بيانات السوق:', error); res.status(500).json({ error: 'حدث خطأ في الحصول على بيانات السوق', details: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }); // وظيفة للحصول على بيانات السوق من مصادر مختلفة async function getMarketData(symbol, timeframe) { // محاولة الحصول على البيانات من Alpha Vantage أولاً try { const response = await apiClient.get( `https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=${symbol}&apikey=${API_KEYS.ALPHAVANTAGE}` ); if (response.data && response.data['Time Series (Daily)']) { const timeSeriesData = response.data['Time Series (Daily)']; const data = { symbol: symbol, data: Object.entries(timeSeriesData).map(([date, values]) => ({ time: date, open: parseFloat(values['1. open']), high: parseFloat(values['2. high']), low: parseFloat(values['3. low']), close: parseFloat(values['4. close']), volume: parseFloat(values['5. volume']) })).sort((a, b) => new Date(b.time) - new Date(a.time)) }; return data; } } catch (error) { console.warn('فشل الحصول على البيانات من Alpha Vantage:', error.message); } // محاولة الحصول على البيانات من Finnhub try { const to = Math.floor(Date.now() / 1000); const from = to - (365 * 24 * 60 * 60); // سنة واحدة const response = await apiClient.get( `https://finnhub.io/api/v1/stock/candle?symbol=${symbol}&resolution=D&from=${from}&to=${to}&token=${API_KEYS.FINNHUB}` ); if (response.data && response.data.s === 'ok' && response.data.t) { const data = { symbol: symbol, data: response.data.t.map((timestamp, i) => ({ time: new Date(timestamp * 1000).toISOString().split('T')[0], open: response.data.o[i], high: response.data.h[i], low: response.data.l[i], close: response.data.c[i], volume: response.data.v[i] })).sort((a, b) => new Date(b.time) - new Date(a.time)) }; return data; } } catch (error) { console.warn('فشل الحصول على البيانات من Finnhub:', error.message); } // إذا فشلت كل المصادر return null; } // مسار صفحة معلومات السهم app.get('/stock/:symbol', async (req, res) => { try { const { symbol } = req.params; const data = await getMarketData(symbol, '1d'); res.render('stock-details', { title: `معلومات السهم ${symbol}`, symbol, data, error: null }); } catch (error) { console.error('خطأ في تحميل معلومات السهم:', error); res.render('stock-details', { title: 'خطأ في تحميل معلومات السهم', symbol: req.params.symbol, data: null, error: 'حدث خطأ في تحميل بيانات السهم' }); } }); // مسار API للحصول على البيانات التاريخية app.get('/api/stock-history/:symbol', async (req, res) => { try { const { symbol } = req.params; const { from, to } = req.query; // استخدام TradingView للحصول على البيانات التاريخية const client = new TradingView.Client(); const chart = new client.Session.Chart(); await chart.setSymbol(symbol); await chart.setTimeframe('D'); // يومي if (from && to) { await chart.setRange(new Date(from), new Date(to)); } const data = await chart.getMarketData(); client.end(); res.json(data); } catch (error) { console.error('خطأ في جلب البيانات التاريخية:', error); res.status(500).json({ error: 'فشل في جلب البيانات التاريخية', details: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }); // Start the server app.listen(PORT, () => { console.log(`الخادم يعمل على المنفذ ${PORT}`); });