Skip to content
This repository was archived by the owner on Jul 5, 2021. It is now read-only.

Commit e3bec2d

Browse files
authored
Merge pull request #33 from TheSnowfield/test
bug fix
2 parents d480b5a + b3ccdc8 commit e3bec2d

4 files changed

Lines changed: 129 additions & 61 deletions

File tree

source/@declares/global.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,20 @@ declare var BOTARCAPI_USERBEST_HISTORY_DEFAULT: number;
1313
declare var BOTARCAPI_AGGREGATE_LIMITATION: number;
1414
declare var BOTARCAPI_AGGREGATE_ENABLED: boolean;
1515
declare var BOTARCAPI_AGGREGATE_CONCURRENT: boolean;
16+
declare var BOTARCAPI_FRONTPROXY_NODES: Array<FontProxyNode>;
17+
18+
interface FontProxyNode {
19+
url: string,
20+
weight: number
21+
enabled: boolean,
22+
}
1623

1724
declare var ARCAPI_RETRY: number;
1825
declare var ARCAPI_VERSION: number;
1926
declare var ARCAPI_APPVERSION: string;
2027
declare var ARCAPI_USERAGENT: string;
2128
declare var ARCAPI_URL: string;
29+
declare var ARCAPI_URL_CODENAME: string;
2230

2331
declare var DATABASE_PATH: string;
2432
declare var SERVER_PORT: number;

source/corefunc/config.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const _default_config: any = {
3636
'BOTARCAPI_FORWARD_TIMESEC_DEFAULT': 10,
3737

3838
// the number of times the callers can extend the valid time of the token
39-
// BotArcAPI will deny the feeds while exceeding the limitation
39+
// BotArcAPI will decline the feeds while exceeding the limitation
4040
'BOTARCAPI_FORWARD_FEED_MAX': 2,
4141

4242
'BOTARCAPI_USERBEST_HISTORY_MAX': 20,
@@ -50,16 +50,27 @@ const _default_config: any = {
5050
// this feature is for 3.6.0 arcapi
5151
'BOTARCAPI_AGGREGATE_ENABLED': false,
5252

53-
// send a huge of requests concurrently
53+
// sending requests concurrently
5454
// only valid on 'BOTARCAPI_AGGREGATE_ENABLED' set to false
5555
'BOTARCAPI_AGGREGATE_CONCURRENT': false,
5656

57+
// frontend http proxy
58+
// used to load balance for per ip
59+
// change this will ignore the 'ARCAPI_URL' config
60+
// if set to '[]' will disable the frontend proxy
61+
'BOTARCAPI_FRONTPROXY_NODES': [
62+
// { url: "https://arcapi.lowiro.com", weight: 1.0 },
63+
// { url: "https://example.com", weight: 0.8 },
64+
// { url: "https://your.proxy.node.com", weight: 0.3 },
65+
],
66+
5767
// arcaea api config
5868
'ARCAPI_RETRY': 3,
5969
'ARCAPI_VERSION': 14,
6070
'ARCAPI_APPVERSION': '3.6.0c',
6171
'ARCAPI_USERAGENT': 'Grievous Lady (Linux; U; Android 2.3.3; BotArcAPI)',
62-
'ARCAPI_URL': 'https://arcapi.lowiro.com/blockchain',
72+
'ARCAPI_URL': 'https://arcapi.lowiro.com',
73+
'ARCAPI_URL_CODENAME': 'blockchain',
6374

6475
// path to database folder
6576
'DATABASE_PATH': './savedata/',

source/modules/arcfetch/arcapi.aggregate.ts

Lines changed: 74 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,74 @@ import arcfetch, { ArcFetchRequest, ArcFetchMethod } from './arcfetch';
55
import IArcAccount from './interfaces/IArcAccount';
66
import arcapi_any from './arcapi.any';
77

8-
export default (account: IArcAccount, endpoints: Array<string>) => {
8+
export default async (account: IArcAccount,
9+
endpoints: Array<string>): Promise<any> => {
10+
11+
// account will be BANNED from server if exceed
12+
if (endpoints.length > BOTARCAPI_AGGREGATE_LIMITATION)
13+
throw new Error('Endpoints limit exceeded');
14+
15+
if (BOTARCAPI_AGGREGATE_ENABLED) {
16+
17+
// construct endpoint object
18+
const _endpoints: Array<any> = [];
19+
endpoints.forEach((element, index) => {
20+
_endpoints.push({ endpoint: element, id: index });
21+
});
22+
23+
// construct remote request
24+
const _remote_request =
25+
new ArcFetchRequest(ArcFetchMethod.GET, 'compose/aggregate', {
26+
deviceId: account.device,
27+
userToken: account.token,
28+
submitData: new URLSearchParams({ 'calls': JSON.stringify(_endpoints) })
29+
});
930

10-
return new Promise(async (resolve, reject) => {
31+
// send request
32+
return arcfetch(_remote_request)
33+
.then((root: any) => {
1134

12-
// account will be BANNED from server if exceed
13-
if (endpoints.length > BOTARCAPI_AGGREGATE_LIMITATION)
14-
return reject(new Error('Endpoints limit exceeded'));
35+
// teardown the object and pack data into array
36+
const _data: Array<any> = [];
37+
root.value.forEach((element: any) => {
38+
_data[element.id] = element.value[0];
39+
})
1540

16-
if (BOTARCAPI_AGGREGATE_ENABLED) {
41+
return _data;
42+
})
43+
.catch((e: string) => {
1744

18-
// construct endpoint object
19-
const _endpoints: Array<any> = [];
20-
endpoints.forEach((element, index) => {
21-
_endpoints.push({ endpoint: element, id: index });
45+
// if token is invalid
46+
// just erase the token and wait for
47+
// auto login in next time allocating
48+
if (e == 'UnauthorizedError') {
49+
account.token = '';
50+
syslog.w(TAG, `Invalid token => ${account.name} ${account.token}`);
51+
}
52+
53+
throw e;
2254
});
2355

24-
// construct remote request
25-
const _remote_request =
26-
new ArcFetchRequest(ArcFetchMethod.GET, 'compose/aggregate', {
27-
deviceId: account.device,
28-
userToken: account.token,
29-
submitData: new URLSearchParams({ 'calls': JSON.stringify(_endpoints) })
30-
});
56+
} else {
57+
if (BOTARCAPI_AGGREGATE_CONCURRENT) {
3158

32-
// send request
33-
arcfetch(_remote_request)
34-
.then((root: any) => {
59+
// construct tasks
60+
const _tasks: Array<Promise<any>> = [];
61+
endpoints.forEach((element, index) => {
62+
_tasks.push(arcapi_any(account, ArcFetchMethod.GET, element, ""));
63+
});
3564

36-
// teardown the object and pack data into array
37-
const _data: Array<any> = [];
38-
root.value.forEach((element: any) => {
39-
_data[element.id] = element.value[0];
40-
})
65+
// wait for data coming in
66+
return Promise.all(_tasks)
67+
.then(data => {
68+
let _results: any[] = [];
69+
70+
data.forEach((element, index) =>
71+
_results.push(element.value[0]));
4172

42-
resolve(_data);
43-
})
44-
.catch((e: string) => {
73+
return _results;
74+
75+
}).catch((e: string) => {
4576

4677
// if token is invalid
4778
// just erase the token and wait for
@@ -50,49 +81,36 @@ export default (account: IArcAccount, endpoints: Array<string>) => {
5081
account.token = '';
5182
syslog.w(TAG, `Invalid token => ${account.name} ${account.token}`);
5283
}
53-
54-
reject(e);
55-
84+
throw e;
5685
});
5786

5887
} else {
59-
if (BOTARCAPI_AGGREGATE_CONCURRENT) {
60-
61-
// construct tasks
62-
const _tasks: Array<Promise<any>> = [];
63-
endpoints.forEach((element, index) => {
64-
_tasks.push(new Promise(async (resolve, reject) => {
65-
resolve(await arcapi_any(account, ArcFetchMethod.GET, element, ""));
66-
}));
67-
});
68-
69-
// wait for data coming in
70-
Promise.all(_tasks)
71-
.then(data => {
72-
let _results: any[] = [];
73-
74-
data.forEach((element, index) =>
75-
_results.push(element.value[0]));
7688

77-
resolve(_results);
89+
let _results: any[] = [];
7890

79-
}).catch((e: string) => reject(e));
80-
81-
} else {
82-
83-
let _results: any[] = [];
91+
try {
8492

8593
// request one by one
8694
for (let i = 0; i < endpoints.length; ++i) {
8795
const _data: any = await arcapi_any(account, ArcFetchMethod.GET, endpoints[i], "");
8896
_results.push(_data.value[0]);
8997
}
98+
return _results;
9099

91-
resolve(_results);
100+
} catch (e) {
101+
102+
// if token is invalid
103+
// just erase the token and wait for
104+
// auto login in next time allocating
105+
if (e == 'UnauthorizedError') {
106+
account.token = '';
107+
syslog.w(TAG, `Invalid token => ${account.name} ${account.token}`);
108+
}
109+
throw e;
92110
}
93111

94112
}
95113

96-
});
114+
}
97115

98116
}

source/modules/arcfetch/arcfetch.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,14 @@ export class ArcFetchRequest extends Request {
3434

3535
// request url
3636
let _request_url: ArcFetchRestUrl =
37-
`${ARCAPI_URL}/${ARCAPI_VERSION}/${resturl}`;
37+
`${do_selectnode()}/${ARCAPI_URL_CODENAME}/${ARCAPI_VERSION}/${resturl}`;
3838

3939
// http headers
4040
const _request_headers: ArcFetchHeaders = {
4141
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
4242
'AppVersion': ARCAPI_APPVERSION,
4343
'User-Agent': ARCAPI_USERAGENT,
4444
'Platform': 'android',
45-
'Host': 'arcapi.lowiro.com',
4645
'Connection': 'Keep-Alive'
4746
}
4847

@@ -91,6 +90,38 @@ export class ArcFetchRequest extends Request {
9190

9291
}
9392

93+
const do_selectnode = (): string => {
94+
95+
if (!BOTARCAPI_FRONTPROXY_NODES.length
96+
|| BOTARCAPI_FRONTPROXY_NODES.length == 0) {
97+
return ARCAPI_URL;
98+
}
99+
100+
let _enabled = [];
101+
let _weight_sum = 0;
102+
103+
// filter the nodes
104+
for (let i = 0; i < BOTARCAPI_FRONTPROXY_NODES.length; ++i) {
105+
if (BOTARCAPI_FRONTPROXY_NODES[i].enabled
106+
|| BOTARCAPI_FRONTPROXY_NODES[i].enabled == undefined) {
107+
_enabled.push(BOTARCAPI_FRONTPROXY_NODES[i]);
108+
_weight_sum += BOTARCAPI_FRONTPROXY_NODES[i].weight;
109+
}
110+
}
111+
112+
// roll a number select node by weight
113+
let roll = Math.random() * _weight_sum;
114+
_weight_sum = 0;
115+
116+
// select a node
117+
for (let i = 0; i < _enabled.length; ++i) {
118+
_weight_sum += _enabled[i].weight;
119+
if (_weight_sum >= roll) return _enabled[i].url;
120+
}
121+
122+
return _enabled[_enabled.length - 1].url;
123+
}
124+
94125
const do_fetch = (request: ArcFetchRequest): Promise<any> => {
95126

96127
// request origin arcapi

0 commit comments

Comments
 (0)