Skip to content

Commit ff56269

Browse files
committed
Fix searchMarket
- Implements searchMarketV3 - Deprecates searchMarket - Deprecates screeners - Uses 'params' field for queryparams - Lint
1 parent 5544817 commit ff56269

2 files changed

Lines changed: 146 additions & 92 deletions

File tree

src/miscRequests.js

Lines changed: 111 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ const validateStatus = (status) => status < 500;
88
const indicators = ['Recommend.Other', 'Recommend.All', 'Recommend.MA'];
99
const builtInIndicList = [];
1010

11-
async function fetchScanData(tickers = [], type = '', columns = []) {
12-
const { data } = await axios.post(`https://scanner.tradingview.com/${type}/scan`, {
13-
symbols: { tickers },
14-
columns,
15-
}, { validateStatus });
11+
async function fetchScanData(tickers = [], columns = []) {
12+
const { data } = await axios.post(
13+
'https://scanner.tradingview.com/global/scan',
14+
{
15+
symbols: { tickers },
16+
columns,
17+
},
18+
{ validateStatus },
19+
);
1620

1721
return data;
1822
}
@@ -40,56 +44,21 @@ async function fetchScanData(tickers = [], type = '', columns = []) {
4044
* }} Periods
4145
*/
4246

43-
// /**
44-
// * @typedef {string | 'forex' | 'crypto'
45-
// * | 'america' | 'australia' | 'canada' | 'egypt'
46-
// * | 'germany' | 'india' | 'israel' | 'italy'
47-
// * | 'luxembourg' | 'poland' | 'sweden' | 'turkey'
48-
// * | 'uk' | 'vietnam'} Screener
49-
// * You can use `getScreener(exchange)` function for non-forex and non-crypto markets.
50-
// */
51-
5247
module.exports = {
53-
// /**
54-
// * Get a screener from an exchange
55-
// * @function getScreener
56-
// * @param {string} exchange Example: BINANCE, EURONEXT, NASDAQ
57-
// * @returns {Screener}
58-
// */
59-
// getScreener(exchange) {
60-
// const e = exchange.toUpperCase();
61-
// if (['NASDAQ', 'NYSE', 'NYSE ARCA', 'OTC'].includes(e)) return 'america';
62-
// if (['ASX'].includes(e)) return 'australia';
63-
// if (['TSX', 'TSXV', 'CSE', 'NEO'].includes(e)) return 'canada';
64-
// if (['EGX'].includes(e)) return 'egypt';
65-
// if (['FWB', 'SWB', 'XETR'].includes(e)) return 'germany';
66-
// if (['BSE', 'NSE'].includes(e)) return 'india';
67-
// if (['TASE'].includes(e)) return 'israel';
68-
// if (['MIL', 'MILSEDEX'].includes(e)) return 'italy';
69-
// if (['LUXSE'].includes(e)) return 'luxembourg';
70-
// if (['NEWCONNECT'].includes(e)) return 'poland';
71-
// if (['NGM'].includes(e)) return 'sweden';
72-
// if (['BIST'].includes(e)) return 'turkey';
73-
// if (['LSE', 'LSIN'].includes(e)) return 'uk';
74-
// if (['HNX'].includes(e)) return 'vietnam';
75-
// return 'global';
76-
// },
77-
7848
/**
7949
* Get technical analysis
8050
* @function getTA
81-
* @param {Screener} screener Market screener
8251
* @param {string} id Full market id (Example: COINBASE:BTCEUR)
8352
* @returns {Promise<Periods>} results
8453
*/
85-
async getTA(screener, id) {
54+
async getTA(id) {
8655
const advice = {};
8756

8857
const cols = ['1', '5', '15', '60', '240', '1D', '1W', '1M']
8958
.map((t) => indicators.map((i) => (t !== '1D' ? `${i}|${t}` : i)))
9059
.flat();
9160

92-
const rs = await fetchScanData([id], screener, cols);
61+
const rs = await fetchScanData([id], cols);
9362
if (!rs.data || !rs.data[0]) return false;
9463

9564
rs.data[0].d.forEach((val, i) => {
@@ -107,53 +76,99 @@ module.exports = {
10776
* @prop {string} id Market full symbol
10877
* @prop {string} exchange Market exchange name
10978
* @prop {string} fullExchange Market exchange full name
110-
* @prop {Screener | 'forex' | 'crypto'} screener Market screener
11179
* @prop {string} symbol Market symbol
11280
* @prop {string} description Market name
11381
* @prop {string} type Market type
11482
* @prop {() => Promise<Periods>} getTA Get market technical analysis
11583
*/
11684

11785
/**
118-
* Find a symbol
86+
* Find a symbol (deprecated)
11987
* @function searchMarket
12088
* @param {string} search Keywords
12189
* @param {'stock'
12290
* | 'futures' | 'forex' | 'cfd'
12391
* | 'crypto' | 'index' | 'economic'
12492
* } [filter] Caterogy filter
12593
* @returns {Promise<SearchMarketResult[]>} Search results
94+
* @deprecated Use searchMarketV3 instead
12695
*/
12796
async searchMarket(search, filter = '') {
12897
const { data } = await axios.get(
129-
`https://symbol-search.tradingview.com/symbol_search/?text=${search.replace(/ /g, '%20')}&type=${filter}`,
98+
'https://symbol-search.tradingview.com/symbol_search',
13099
{
131-
validateStatus,
100+
params: {
101+
text: search.replace(/ /g, '%20'),
102+
type: filter,
103+
},
132104
headers: {
133105
origin: 'https://www.tradingview.com',
134106
},
107+
validateStatus,
135108
},
136109
);
137110

138111
return data.map((s) => {
139112
const exchange = s.exchange.split(' ')[0];
140113
const id = `${exchange}:${s.symbol}`;
141114

142-
// const screener = (['forex', 'crypto'].includes(s.type)
143-
// ? s.type
144-
// : this.getScreener(exchange)
145-
// );
146-
const screener = 'global';
115+
return {
116+
id,
117+
exchange,
118+
fullExchange: s.exchange,
119+
symbol: s.symbol,
120+
description: s.description,
121+
type: s.type,
122+
getTA: () => this.getTA(id),
123+
};
124+
});
125+
},
126+
127+
/**
128+
* Find a symbol
129+
* @function searchMarketV3
130+
* @param {string} search Keywords
131+
* @param {'stock'
132+
* | 'futures' | 'forex' | 'cfd'
133+
* | 'crypto' | 'index' | 'economic'
134+
* } [filter] Caterogy filter
135+
* @returns {Promise<SearchMarketResult[]>} Search results
136+
*/
137+
async searchMarketV3(search, filter = '') {
138+
const splittedSearch = search.toUpperCase().replace(/ /g, '+').split(':');
139+
140+
const request = await axios.get(
141+
'https://symbol-search.tradingview.com/symbol_search/v3',
142+
{
143+
params: {
144+
exchange: (splittedSearch.length === 2
145+
? splittedSearch[0]
146+
: undefined
147+
),
148+
text: splittedSearch.pop(),
149+
search_type: filter,
150+
},
151+
headers: {
152+
origin: 'https://www.tradingview.com',
153+
},
154+
validateStatus,
155+
},
156+
);
157+
158+
const { data } = request;
159+
160+
return data.symbols.map((s) => {
161+
const exchange = s.exchange.split(' ')[0];
162+
const id = `${exchange.toUpperCase()}:${s.symbol}`;
147163

148164
return {
149165
id,
150166
exchange,
151167
fullExchange: s.exchange,
152-
screener,
153168
symbol: s.symbol,
154169
description: s.description,
155170
type: s.type,
156-
getTA: () => this.getTA(screener, id),
171+
getTA: () => this.getTA(id),
157172
};
158173
});
159174
},
@@ -182,16 +197,26 @@ module.exports = {
182197
if (!builtInIndicList.length) {
183198
await Promise.all(['standard', 'candlestick', 'fundamental'].map(async (type) => {
184199
const { data } = await axios.get(
185-
`https://pine-facade.tradingview.com/pine-facade/list/?filter=${type}`,
186-
{ validateStatus },
200+
'https://pine-facade.tradingview.com/pine-facade/list',
201+
{
202+
params: {
203+
filter: type,
204+
},
205+
validateStatus,
206+
},
187207
);
188208
builtInIndicList.push(...data);
189209
}));
190210
}
191211

192212
const { data } = await axios.get(
193-
`https://www.tradingview.com/pubscripts-suggest-json/?search=${search.replace(/ /g, '%20')}`,
194-
{ validateStatus },
213+
'https://www.tradingview.com/pubscripts-suggest-json',
214+
{
215+
params: {
216+
search: search.replace(/ /g, '%20'),
217+
},
218+
validateStatus,
219+
},
195220
);
196221

197222
function norm(str = '') {
@@ -253,10 +278,10 @@ module.exports = {
253278
const { data } = await axios.get(
254279
`https://pine-facade.tradingview.com/pine-facade/translate/${indicID}/${version}`,
255280
{
256-
validateStatus,
257281
headers: {
258282
cookie: `${session ? `sessionid=${session};` : ''}${signature ? `sessionid_sign=${signature};` : ''}`,
259283
},
284+
validateStatus,
260285
},
261286
);
262287

@@ -356,12 +381,12 @@ module.exports = {
356381
'https://www.tradingview.com/accounts/signin/',
357382
`username=${username}&password=${password}${remember ? '&remember=on' : ''}`,
358383
{
359-
validateStatus,
360384
headers: {
361385
referer: 'https://www.tradingview.com',
362386
'Content-Type': 'application/x-www-form-urlencoded',
363387
'User-agent': `${UA} (${os.version()}; ${os.platform()}; ${os.arch()})`,
364388
},
389+
validateStatus,
365390
},
366391
);
367392

@@ -403,10 +428,10 @@ module.exports = {
403428
*/
404429
async getUser(session, signature = '', location = 'https://www.tradingview.com/') {
405430
const { data } = await axios.get(location, {
406-
validateStatus,
407431
headers: {
408432
cookie: `sessionid=${session}${signature ? `;sessionid_sign=${signature};` : ''}`,
409433
},
434+
validateStatus,
410435
});
411436

412437
if (data.includes('auth_token')) {
@@ -442,12 +467,18 @@ module.exports = {
442467
* @returns {Promise<SearchIndicatorResult[]>} Search results
443468
*/
444469
async getPrivateIndicators(session, signature = '') {
445-
const { data } = await axios.get('https://pine-facade.tradingview.com/pine-facade/list?filter=saved', {
446-
validateStatus,
447-
headers: {
448-
cookie: `sessionid=${session}${signature ? `;sessionid_sign=${signature};` : ''}`,
470+
const { data } = await axios.get(
471+
'https://pine-facade.tradingview.com/pine-facade/list',
472+
{
473+
headers: {
474+
cookie: `sessionid=${session}${signature ? `;sessionid_sign=${signature};` : ''}`,
475+
},
476+
params: {
477+
filter: 'saved',
478+
},
479+
validateStatus,
449480
},
450-
});
481+
);
451482

452483
return data.map((ind) => ({
453484
id: ind.scriptIdPart,
@@ -495,14 +526,18 @@ module.exports = {
495526
);
496527

497528
const { data } = await axios.get(
498-
`https://www.tradingview.com/chart-token/?image_url=${layout}&user_id=${id}`,
529+
'https://www.tradingview.com/chart-token',
499530
{
500-
validateStatus,
501531
headers: {
502532
cookie: session
503533
? `sessionid=${session}${signature ? `;sessionid_sign=${signature};` : ''}`
504534
: '',
505535
},
536+
params: {
537+
image_url: layout,
538+
user_id: id,
539+
},
540+
validateStatus,
506541
},
507542
);
508543

@@ -548,14 +583,15 @@ module.exports = {
548583
const { data } = await axios.get(
549584
`https://charts-storage.tradingview.com/charts-storage/get/layout/${
550585
layout
551-
}/sources?chart_id=${
552-
chartID
553-
}&jwt=${
554-
chartToken
555-
}${
556-
(symbol ? `&symbol=${symbol}` : '')
557-
}`,
558-
{ validateStatus },
586+
}/sources`,
587+
{
588+
params: {
589+
chart_id: chartID,
590+
jwt: chartToken,
591+
symbol,
592+
},
593+
validateStatus,
594+
},
559595
);
560596

561597
if (!data.payload) throw new Error('Wrong layout, user credentials, or chart id.');

0 commit comments

Comments
 (0)