r6-data.js 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -111,21 +111,87 @@ The `getPlayerStats()` function accepts an object with the following parameters:
111
111
  - `board_id`: (Optional) The game mode to filter statistics - "casual", "event", "warmup", "standard", or "ranked"
112
112
 
113
113
  ### Player Statistics Response
114
- When using `getPlayerStats()`, you'll receive detailed gameplay statistics, including:
114
+ When using `getPlayerStats()`, you'll receive detailed gameplay statistics, including:
115
115
 
116
- - Rank information
117
- - MMR (Matchmaking Rating)
118
- - Win/loss records
119
- - Seasonal performance data
120
- - Skill metrics across different gameplay modes
116
+ - Rank information
117
+ - MMR (Matchmaking Rating)
118
+ - Win/loss records
119
+ - Seasonal performance data
120
+ - Skill metrics across different gameplay modes
121
121
 
122
- You can filter these statistics by game mode using the `board_id` parameter:
122
+ You can filter these statistics by game mode using the `board_id` parameter:
123
123
 
124
- - `casual`: Statistics for casual matches
125
- - `event`: Statistics for limited-time events
126
- - `warmup`: Statistics for warmup matches
127
- - `standard`: Statistics for standard matches
128
- - `ranked`: Statistics for ranked competitive matches
124
+ - `casual`: Statistics for casual matches
125
+ - `event`: Statistics for limited-time events
126
+ - `warmup`: Statistics for warmup matches
127
+ - `standard`: Statistics for standard matches
128
+ - `ranked`: Statistics for ranked competitive matches
129
+
130
+ ## Creating Discord Webhooks for R6 Stats
131
+
132
+ The `createDiscordR6Webhook()` function allows you to send Rainbow Six Siege player statistics directly to a Discord channel using webhooks. This creates formatted embeds with player stats that can be customized with various options.
133
+
134
+ ```javascript
135
+ const r6Info = require('r6-data.js');
136
+
137
+ async function main() {
138
+ try {
139
+ // First, get player statistics
140
+ const playerStats = await r6Info.getPlayerStats({
141
+ nameOnPlatform: 'PlayerName',
142
+ platformType: 'uplay',
143
+ platform_families: 'pc'
144
+ });
145
+
146
+ // Send stats to Discord webhook
147
+ const webhookResult = await r6Info.createDiscordR6Webhook(
148
+ 'https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN',
149
+ playerStats,
150
+ {
151
+ playerName: 'PlayerName',
152
+ title: 'Rainbow Six Siege Stats',
153
+ message: 'Here are the latest R6 stats!',
154
+ color: 0xF99E1A, // Orange color
155
+ avatarUrl: 'https://example.com/avatar.png'
156
+ }
157
+ );
158
+
159
+ console.log('Webhook sent successfully:', webhookResult);
160
+
161
+ } catch (error) {
162
+ console.error('Error sending webhook:', error.message);
163
+ }
164
+ }
165
+
166
+ main();
167
+ ```
168
+
169
+ ### Parameters
170
+ The `createDiscordR6Webhook()` function accepts the following parameters:
171
+ - `webhookUrl`: (Required) The Discord webhook URL
172
+ - `playerData`: (Required) Player statistics data from getPlayerStats() or getAccountInfo()
173
+ - `options`: (Required) Configuration object with the following properties:
174
+ - `playerName`: (Required) The player's name to display
175
+ - `title`: (Optional) Custom title for the embed (default: "Rainbow Six Siege Stats")
176
+ - `message`: (Optional) Custom message content above the embed
177
+ - `color`: (Optional) Embed color in hexadecimal format (default: 0xF99E1A)
178
+ - `avatarUrl`: (Optional) URL for the player's avatar thumbnail
179
+
180
+ ### Supported Data Formats
181
+ The function automatically detects and formats different data sources:
182
+
183
+ `Ubisoft API data`: From getPlayerStats() - displays ranked/standard statistics
184
+ `Steam data`: Custom Steam-formatted statistics
185
+ `Custom data`: Any custom statistics object
186
+
187
+ ### Discord Webhook Setup
188
+ To use this function, you need to create a webhook in your Discord server:
189
+
190
+ 1. Go to your Discord server settings
191
+ 2. Navigate to Integrations → Webhooks
192
+ 3. Click "New Webhook"
193
+ 4. Copy the webhook URL
194
+ 5. Use this URL in the `createDiscordR6Webhook()` function
129
195
 
130
196
  ## Searching Across All Entities
131
197
 
package/index.js CHANGED
@@ -10,6 +10,7 @@ const getUniversalSkins = require('./methods/getUniversalSkins');
10
10
  const getSearchAll = require('./methods/getSearchAll');
11
11
  const getAccountInfo = require('./methods/getAccountInfo');
12
12
  const getPlayerStats = require('./methods/getPlayerStats');
13
+ const createDiscordR6Webhook = require('./methods/createDiscordR6Webhook');
13
14
 
14
15
  const r6Data = {
15
16
  getMaps,
@@ -24,6 +25,7 @@ const r6Data = {
24
25
  getSearchAll,
25
26
  getAccountInfo,
26
27
  getPlayerStats,
28
+ createDiscordR6Webhook,
27
29
  };
28
30
 
29
31
  module.exports = r6Data;
@@ -0,0 +1,217 @@
1
+ const axiosInstance = require('../axiosInstance/axiosInstance');
2
+
3
+ async function createDiscordR6Webhook(webhookUrl, playerData, options = {}) {
4
+ try {
5
+ if (!webhookUrl || !playerData) {
6
+ throw new Error('Missing required parameters: webhookUrl and playerData are required');
7
+ }
8
+
9
+ if (!options.playerName) {
10
+ throw new Error('Missing required parameter: options.playerName is required');
11
+ }
12
+
13
+ // Validate webhook URL format
14
+ if (!webhookUrl.includes('discord.com/api/webhooks/')) {
15
+ throw new Error('Invalid Discord webhook URL format');
16
+ }
17
+
18
+ const embed = createR6StatsEmbed(playerData, options);
19
+
20
+ const payload = {
21
+ embeds: [embed]
22
+ };
23
+
24
+ // Add custom message if provided
25
+ if (options.message) {
26
+ payload.content = options.message;
27
+ }
28
+
29
+ const response = await axiosInstance.post(webhookUrl, payload);
30
+
31
+ return {
32
+ success: true,
33
+ messageId: response.headers['x-discord-message-id'],
34
+ sentAt: new Date().toISOString()
35
+ };
36
+
37
+ } catch (error) {
38
+ console.error('Error during createDiscordR6Webhook request:', error.message);
39
+ if (error.response && error.response.status === 404) {
40
+ throw new Error('Discord webhook not found - check webhook URL');
41
+ }
42
+ if (error.response && error.response.status === 401) {
43
+ throw new Error('Discord webhook unauthorized - webhook may be disabled');
44
+ }
45
+ if (error.response && error.response.status === 429) {
46
+ throw new Error('Discord rate limit exceeded - try again later');
47
+ }
48
+ throw error;
49
+ }
50
+ }
51
+
52
+ function createR6StatsEmbed(playerData, options) {
53
+ let stats, dataSource;
54
+
55
+ if (playerData.stats) {
56
+ // Steam data format
57
+ stats = playerData.stats;
58
+ dataSource = 'Steam';
59
+ } else if (playerData.platform_families_full_profiles) {
60
+ // Ubisoft API data format - from getStats method
61
+ stats = parseUbisoftStatsFromResponse(playerData);
62
+ dataSource = 'Ubisoft';
63
+ } else if (Array.isArray(playerData)) {
64
+ // Ubisoft API data format - direct array
65
+ stats = parseUbisoftStats(playerData);
66
+ dataSource = 'Ubisoft';
67
+ } else {
68
+ // Fallback
69
+ stats = playerData;
70
+ dataSource = 'Custom';
71
+ }
72
+
73
+ const embed = {
74
+ title: `${options.title || 'Rainbow Six Siege Stats'}`,
75
+ description: `Stats for **${options.playerName}**`,
76
+ color: options.color || 0xF99E1A,
77
+ fields: createStatsFields(stats, dataSource),
78
+ thumbnail: {
79
+ url: options.avatarUrl || 'https://ubisoft-avatars.akamaized.net/default_256_256.png'
80
+ },
81
+ footer: {
82
+ text: `Data from ${dataSource} | r6-data.js`
83
+ },
84
+ timestamp: new Date().toISOString()
85
+ };
86
+
87
+ return embed;
88
+ }
89
+
90
+ function parseUbisoftStatsFromResponse(response) {
91
+ const platformProfile = response.platform_families_full_profiles[0];
92
+ if (!platformProfile || !platformProfile.board_ids_full_profiles) {
93
+ return { ranked: null, standard: null };
94
+ }
95
+
96
+ const boardsArray = platformProfile.board_ids_full_profiles;
97
+ return parseUbisoftStats(boardsArray);
98
+ }
99
+
100
+ function parseUbisoftStats(data) {
101
+ let rankedStats = null;
102
+ let standardStats = null;
103
+
104
+ for (const board of data) {
105
+ if (board.board_id === 'ranked' && board.full_profiles && board.full_profiles[0]) {
106
+ rankedStats = {
107
+ profile: board.full_profiles[0].profile,
108
+ season_statistics: board.full_profiles[0].season_statistics
109
+ };
110
+ }
111
+
112
+ if (board.board_id === 'standard' && board.full_profiles && board.full_profiles[0]) {
113
+ standardStats = {
114
+ profile: board.full_profiles[0].profile,
115
+ season_statistics: board.full_profiles[0].season_statistics
116
+ };
117
+ }
118
+ }
119
+
120
+ return {
121
+ ranked: rankedStats,
122
+ standard: standardStats
123
+ };
124
+ }
125
+
126
+ function createStatsFields(stats, dataSource) {
127
+ const fields = [];
128
+
129
+ if (dataSource === 'Steam') {
130
+ fields.push(
131
+ {
132
+ name: 'General Stats',
133
+ value: `**Matches Played:** ${stats.generalStats?.matchesPlayed || 'N/A'}\n**Win Rate:** ${stats.generalStats?.winRate || 0}%\n**Playtime:** ${stats.generalStats?.totalTimePlayedHours || 0}h`,
134
+ inline: true
135
+ },
136
+ {
137
+ name: 'Combat Stats',
138
+ value: `**K/D Ratio:** ${stats.combatStats?.kdRatio || 'N/A'}\n**Total Kills:** ${stats.combatStats?.totalKills || 'N/A'}\n**Headshot %:** ${stats.combatStats?.headshotPercentage || 0}%`,
139
+ inline: true
140
+ },
141
+ {
142
+ name: 'Ranked Stats',
143
+ value: `**Ranked Matches:** ${stats.rankedStats?.rankedMatches || 'N/A'}\n**Ranked K/D:** ${stats.rankedStats?.rankedKD || 'N/A'}\n**Ranked Win Rate:** ${stats.rankedStats?.rankedWinRate || 0}%`,
144
+ inline: true
145
+ }
146
+ );
147
+ } else if (dataSource === 'Ubisoft') {
148
+ const rankedData = stats.ranked;
149
+
150
+ if (rankedData && rankedData.profile && rankedData.season_statistics) {
151
+ const profile = rankedData.profile;
152
+ const seasonStats = rankedData.season_statistics;
153
+
154
+ const totalMatches = (seasonStats.match_outcomes.wins || 0) + (seasonStats.match_outcomes.losses || 0);
155
+ const winRate = totalMatches > 0 ? Math.round((seasonStats.match_outcomes.wins / totalMatches) * 100) : 0;
156
+ const kd = seasonStats.deaths > 0 ? Math.round((seasonStats.kills / seasonStats.deaths) * 100) / 100 : seasonStats.kills;
157
+
158
+ fields.push(
159
+ {
160
+ name: 'Ranked Profile',
161
+ value: `**Rank:** ${getRankName(profile.rank)}\n**Points:** ${profile.rank_points}\n**Max Rank:** ${getRankName(profile.max_rank)}`,
162
+ inline: true
163
+ },
164
+ {
165
+ name: 'Performance',
166
+ value: `**K/D:** ${kd}\n**Win Rate:** ${winRate}%\n**Matches:** ${totalMatches}`,
167
+ inline: true
168
+ },
169
+ {
170
+ name: 'Combat Stats',
171
+ value: `**Kills:** ${seasonStats.kills}\n**Deaths:** ${seasonStats.deaths}\n**Wins:** ${seasonStats.match_outcomes.wins}\n**Losses:** ${seasonStats.match_outcomes.losses}`,
172
+ inline: true
173
+ }
174
+ );
175
+ } else {
176
+ // Fallback to standard stats if ranked not available
177
+ const standardData = stats.standard;
178
+ if (standardData && standardData.season_statistics) {
179
+ const seasonStats = standardData.season_statistics;
180
+ const totalMatches = (seasonStats.match_outcomes.wins || 0) + (seasonStats.match_outcomes.losses || 0);
181
+ const winRate = totalMatches > 0 ? Math.round((seasonStats.match_outcomes.wins / totalMatches) * 100) : 0;
182
+ const kd = seasonStats.deaths > 0 ? Math.round((seasonStats.kills / seasonStats.deaths) * 100) / 100 : seasonStats.kills;
183
+
184
+ fields.push({
185
+ name: 'Standard Stats',
186
+ value: `**K/D:** ${kd}\n**Win Rate:** ${winRate}%\n**Matches:** ${totalMatches}\n**Kills:** ${seasonStats.kills}\n**Deaths:** ${seasonStats.deaths}`,
187
+ inline: false
188
+ });
189
+ } else {
190
+ fields.push({
191
+ name: 'No Data',
192
+ value: 'No ranked or standard stats available.',
193
+ inline: false
194
+ });
195
+ }
196
+ }
197
+ }
198
+
199
+ return fields;
200
+ }
201
+
202
+ function getRankName(rankNumber) {
203
+ const ranks = {
204
+ 0: 'Unranked',
205
+ 1: 'Copper V', 2: 'Copper IV', 3: 'Copper III', 4: 'Copper II', 5: 'Copper I',
206
+ 6: 'Bronze V', 7: 'Bronze IV', 8: 'Bronze III', 9: 'Bronze II', 10: 'Bronze I',
207
+ 11: 'Silver V', 12: 'Silver IV', 13: 'Silver III', 14: 'Silver II', 15: 'Silver I',
208
+ 16: 'Gold V', 17: 'Gold IV', 18: 'Gold III', 19: 'Gold II', 20: 'Gold I',
209
+ 21: 'Platinum V', 22: 'Platinum IV', 23: 'Platinum III', 24: 'Platinum II', 25: 'Platinum I',
210
+ 26: 'Diamond V', 27: 'Diamond IV', 28: 'Diamond III', 29: 'Diamond II', 30: 'Diamond I',
211
+ 31: 'Champion'
212
+ };
213
+
214
+ return ranks[rankNumber] || 'Unknown Rank';
215
+ }
216
+
217
+ module.exports = createDiscordR6Webhook;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "r6-data.js",
3
- "version": "1.2.1",
4
- "description": "Rainbow Six Siege API wrapper that gives infos about player's stats, maps, operators, ranks, seasons, charms etc. Last updated Y10S3",
3
+ "version": "1.3.1",
4
+ "description": "Rainbow Six Siege API wrapper for player's stats, maps, operators, ranks, seasons, charms etc. Last updated Y10S3",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -39,15 +39,20 @@
39
39
  "r6stats-api",
40
40
  "siegeapi",
41
41
  "siege-api",
42
- "siege x api"
42
+ "siege x api",
43
+ "r6siege",
44
+ "rainbow",
45
+ "r6 info",
46
+ "r6-info",
47
+ "R6 info"
43
48
  ],
44
49
  "author": "mazeor",
45
50
  "license": "ISC",
46
51
  "dependencies": {
47
- "axios": "^1.11.0",
52
+ "axios": "^1.12.2",
48
53
  "ms": "^2.1.3"
49
54
  },
50
55
  "devDependencies": {
51
- "@types/node": "^22.15.3"
56
+ "@types/node": "^24.4.0"
52
57
  }
53
58
  }