Skip to content
This repository was archived by the owner on Sep 13, 2025. It is now read-only.

Commit 89f0f27

Browse files
committed
Minor Update
1. New methods for purchases have been added. You can now submit/modify or delete feedback to your purchase. 2. Fixes and improvements.
1 parent 9917d3d commit 89f0f27

File tree

7 files changed

+139
-46
lines changed

7 files changed

+139
-46
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "funpay-api",
3-
"version": "1.0.1",
3+
"version": "1.1.0",
44
"description": "API for FunPay",
55
"type": "module",
66
"main": "dist/index.js",

src/@types/purchases.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type RatingReviews = 1 | 2 | 3 | 4 | 5;

src/API/profile.ts

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Imports
22
import axios from 'axios';
3+
import { isTokenValid, getAccountCredentials } from '../util.js';
34
import { APIFunPayUrls } from '../enums/funpay.js';
45
import { FunPayProfileType } from '../@types/profile.js';
56

@@ -9,24 +10,8 @@ import { FunPayProfileType } from '../@types/profile.js';
910
* @param {string} token - FunPay API token
1011
*/
1112
class FunPayProfile {
12-
private headers: object;
13-
1413
constructor(private token: string) {
1514
this.token = token;
16-
this.headers = {
17-
Cookie: `golden_key=${this.token}`
18-
};
19-
};
20-
21-
private async isTokenValid(): Promise<boolean> {
22-
const { data } = await axios.get(APIFunPayUrls.getIdProfile, {
23-
headers: {
24-
...this.headers
25-
}
26-
});
27-
28-
const hasId = data.match(/<a href="https:\/\/funpay.com\/users\/(.*)\/" class="user-link-dropdown">/g);
29-
return !!hasId;
3015
};
3116

3217
/**
@@ -35,21 +20,10 @@ class FunPayProfile {
3520
* @returns {Promise<FunPayProfileType>} Profile
3621
**/
3722
public async getProfile(): Promise<FunPayProfileType> {
38-
const tokenValid = await this.isTokenValid();
39-
if (!tokenValid)
40-
throw new Error('Invalid token');
41-
42-
const { data } = await axios.get(APIFunPayUrls.getIdProfile, {
43-
headers: {
44-
...this.headers
45-
}
46-
});
23+
const littleInfo = await getAccountCredentials(this.token);
24+
const link = `https://funpay.com/users/${littleInfo.id}/`;
4725

48-
const id = data.match(/<a href="https:\/\/funpay.com\/users\/(.*)\/" class="user-link-dropdown">/g)[0].match(/\/users\/(.*)\//g)[0].replace(/\/users\/|\/|"/g, '');
49-
const link = `https://funpay.com/users/${id}/`;
50-
const name = data.match(/<div class="user-link-name">(.*)<\/div>/g)[0].match(/>(.*)</g)[0].replace(/<|>/g, '');
51-
52-
const getProfile = await axios.get(`${APIFunPayUrls.getProfile}${id}/`);
26+
const getProfile = await axios.get(`${APIFunPayUrls.GET_PROFILE}${littleInfo.id}/`);
5327
const profileData = getProfile.data;
5428

5529
const hasRating = profileData.match(/<span class="big">(.*)<\/span>/g);
@@ -58,12 +32,12 @@ class FunPayProfile {
5832
const hasReviews = profileData.match(/<div class="text-mini text-light mb5">(.*)<\/div>/g);
5933
const totalReviews = hasReviews ? +hasReviews[0].match(/>(.*?)</)[1].match(/\d+/)[0] : 0;
6034

35+
const avatarPhoto = profileData.match(/<div class="avatar-photo" style="background-image: url\((.*)\);"><\/div>/g)[0].match(/url\((.*)\)/g)[0].replace(/url\(|\)/g, '');
36+
6137
return {
62-
id,
63-
link,
64-
name,
65-
avatarPhoto: profileData.match(/<div class="avatar-photo" style="background-image: url\((.*)\);"><\/div>/g)[0].match(/url\((.*)\)/g)[0].replace(/url\(|\)/g, ''),
66-
rating: rating,
38+
id: littleInfo.id,
39+
link, name: littleInfo.name,
40+
avatarPhoto, rating: rating,
6741
totalReviews: totalReviews
6842
};
6943
};
@@ -74,13 +48,13 @@ class FunPayProfile {
7448
* @returns {Promise<number>} Unread messages
7549
**/
7650
public async getUnreadMessages(): Promise<number> {
77-
const tokenValid = await this.isTokenValid();
51+
const tokenValid = await isTokenValid(this.token);
7852
if (!tokenValid)
7953
throw new Error('Invalid token');
8054

81-
const { data } = await axios.get(APIFunPayUrls.getIdProfile, {
55+
const { data } = await axios.get(APIFunPayUrls.GET_ID_PROFILE, {
8256
headers: {
83-
...this.headers
57+
Cookie: `golden_key=${this.token}`
8458
}
8559
});
8660

@@ -95,13 +69,13 @@ class FunPayProfile {
9569
* @returns {Promise<number>} Balance
9670
**/
9771
public async getBalance(): Promise<number> {
98-
const tokenValid = await this.isTokenValid();
72+
const tokenValid = await isTokenValid(this.token);
9973
if (!tokenValid)
10074
throw new Error('Invalid token');
10175

102-
const { data } = await axios.get(APIFunPayUrls.getBalance, {
76+
const { data } = await axios.get(APIFunPayUrls.GET_BALANCE, {
10377
headers: {
104-
...this.headers
78+
Cookie: `golden_key=${this.token}`
10579
}
10680
});
10781

src/API/purchases.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Imports
2+
import axios, { toFormData } from 'axios';
3+
import { getAccountCredentials } from '../util.js';
4+
import { RatingReviews } from '../@types/purchases.js';
5+
import { APIFunPayUrls } from '../enums/funpay.js';
6+
7+
/**
8+
* @class FunPayPurchases
9+
* @description A class that provides methods for working with purchases
10+
* @param {string} token - FunPay API token
11+
*/
12+
class FunPayPurchases {
13+
constructor(private token: string) {
14+
this.token = token;
15+
};
16+
17+
/**
18+
* @method sendReview
19+
* @description Change/add review to Purchase
20+
* @returns {Promise<string>} HTML content
21+
**/
22+
public async sendReview(orderId: string, text: string, rating: RatingReviews = 5): Promise<string> {
23+
const accountCredentials = await getAccountCredentials(this.token);
24+
const payload = toFormData({
25+
'authorId': accountCredentials.id,
26+
'text': text,
27+
'rating': rating,
28+
'csrf_token': accountCredentials.csrfToken,
29+
'orderId': orderId
30+
});
31+
32+
const { data } = await axios.post(APIFunPayUrls.SEND_REVIEW, payload, {
33+
headers: {
34+
'Accept': '*/*',
35+
'X-Requested-With': 'XMLHttpRequest',
36+
'Cookie': `golden_key=${this.token}; PHPSESSID=${accountCredentials.phpSessionId}`,
37+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36'
38+
}
39+
});
40+
41+
return data.content;
42+
};
43+
44+
/**
45+
* @method deleteReview
46+
* @description Delete review from Purchase
47+
* @returns {Promise<string>} HTML content
48+
**/
49+
public async deleteReview(orderId: string): Promise<string> {
50+
const accountCredentials = await getAccountCredentials(this.token);
51+
const payload = toFormData({
52+
'authorId': accountCredentials.id,
53+
'csrf_token': accountCredentials.csrfToken,
54+
'orderId': orderId
55+
});
56+
57+
const { data } = await axios.post(APIFunPayUrls.DELETE_REVIEW, payload, {
58+
headers: {
59+
'Accept': '*/*',
60+
'X-Requested-With': 'XMLHttpRequest',
61+
'Cookie': `golden_key=${this.token}; PHPSESSID=${accountCredentials.phpSessionId}`,
62+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36'
63+
}
64+
});
65+
66+
return data.content;
67+
};
68+
};
69+
70+
export default FunPayPurchases;

src/enums/funpay.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
export enum APIFunPayUrls {
2-
getIdProfile = 'https://funpay.com/',
3-
getProfile = 'https://funpay.com/users/',
4-
getBalance = 'https://funpay.com/account/balance'
2+
GET_ID_PROFILE = 'https://funpay.com/',
3+
GET_PROFILE = 'https://funpay.com/users/',
4+
GET_BALANCE = 'https://funpay.com/account/balance',
5+
6+
SEND_REVIEW = 'https://funpay.com/orders/review',
7+
DELETE_REVIEW = 'https://funpay.com/orders/reviewDelete'
58
};

src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Imports
22
import FunPayProfile from './API/profile.js';
3+
import FunPayPurchases from './API/purchases.js';
34

45
/**
56
* @class FunPayAPI
@@ -8,9 +9,11 @@ import FunPayProfile from './API/profile.js';
89
*/
910
class FunPayAPI {
1011
public Profile: FunPayProfile;
12+
public Purchases: FunPayPurchases;
1113

12-
constructor(token: string) {
14+
constructor(private token: string) {
1315
this.Profile = new FunPayProfile(token);
16+
this.Purchases = new FunPayPurchases(token);
1417
};
1518
};
1619

src/util.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Imports
2+
import axios from 'axios';
3+
import { APIFunPayUrls } from './enums/funpay.js';
4+
// Functions
5+
const isTokenValid = async (token: string): Promise<boolean> => {
6+
if (!token)
7+
throw new Error('Token not provided');
8+
9+
const { data } = await axios.get(APIFunPayUrls.GET_ID_PROFILE, {
10+
headers: {
11+
Cookie: `golden_key=${token}`
12+
}
13+
});
14+
15+
const hasId = data.match(/<a href="https:\/\/funpay.com\/users\/(.*)\/" class="user-link-dropdown">/g);
16+
return !!hasId;
17+
};
18+
19+
const getAccountCredentials = async (token: string): Promise<{ id: number, name: string, csrfToken: string, phpSessionId: string }> => {
20+
const tokenValid = await isTokenValid(token);
21+
if (!tokenValid)
22+
throw new Error('Invalid token');
23+
24+
const { headers, data } = await axios.get(APIFunPayUrls.GET_ID_PROFILE, {
25+
headers: {
26+
Cookie: `golden_key=${token}`
27+
}
28+
});
29+
30+
const phpSessionId = headers['set-cookie']!.find(i => i.includes('PHPSESSID'))?.split(';')[0].split('=')[1];;
31+
if (!phpSessionId)
32+
throw new Error('PHPSESSID not found');
33+
34+
return {
35+
id: +data.match(/<a href="https:\/\/funpay.com\/users\/(.*)\/" class="user-link-dropdown">/g)[0].match(/\/users\/(.*)\//g)[0].replace(/\/users\/|\/|"/g, ''),
36+
name: data.match(/<div class="user-link-name">(.*)<\/div>/g)[0].match(/>(.*)</g)[0].replace(/<|>/g, ''),
37+
csrfToken: data.match(/data-app-data="(.*)"/g)[0].match(/csrf-token&quot;:&quot;(.*)&quot;,&quot;userId&quot;/g)[0].replace(/csrf-token&quot;:&quot;|&quot;,&quot;userId&quot;/g, ''),
38+
phpSessionId
39+
};
40+
};
41+
42+
export { isTokenValid, getAccountCredentials };

0 commit comments

Comments
 (0)