haxball.js 2.3.0 โ†’ 2.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.
@@ -4,7 +4,6 @@ about: Create a report to help us improve
4
4
  title: ''
5
5
  labels: bug
6
6
  assignees: mertushka
7
-
8
7
  ---
9
8
 
10
9
  **Describe the bug**
@@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
12
11
 
13
12
  **To Reproduce**
14
13
  Steps to reproduce the behavior:
14
+
15
15
  1. `npm install haxball.js` '...'
16
16
  2. ...
17
17
 
@@ -22,8 +22,9 @@ A clear and concise description of what you expected to happen.
22
22
  If applicable, add screenshots to help explain your problem.
23
23
 
24
24
  **Device (please complete the following information):**
25
- - OS: [e.g. W11]
26
- - Node.JS Version [e.g. 20.x LTS]
25
+
26
+ - OS: [e.g. W11]
27
+ - Node.JS Version [e.g. 20.x LTS]
27
28
 
28
29
  **Additional context**
29
30
  Add any other context about the problem here.
@@ -4,7 +4,6 @@ about: Suggest an idea for this project
4
4
  title: ''
5
5
  labels: enhancement
6
6
  assignees: ''
7
-
8
7
  ---
9
8
 
10
9
  **Is your feature request related to a problem? Please describe.**
@@ -2,12 +2,20 @@ name: ๐Ÿš€ Haxball.JS CI/CD
2
2
 
3
3
  on:
4
4
  schedule:
5
- - cron: "0 0 * * 0" # Run at 00:00 on Sunday
5
+ - cron: '0 0 * * 0' # Run at 00:00 on Sunday
6
6
  workflow_dispatch: # Allow manual triggers
7
7
  push:
8
- branches: [main, develop]
8
+ branches: [main]
9
+ paths:
10
+ - 'scripts/nodeify.js'
11
+ - 'package.json'
12
+ - 'package-lock.json'
9
13
  pull_request:
10
14
  branches: [main]
15
+ paths:
16
+ - 'scripts/nodeify.js'
17
+ - 'package.json'
18
+ - 'package-lock.json'
11
19
 
12
20
  jobs:
13
21
  build:
@@ -21,8 +29,8 @@ jobs:
21
29
  - name: ๐Ÿ“ฆ Setup Node.js
22
30
  uses: actions/setup-node@v3
23
31
  with:
24
- node-version: 20.x
25
- cache: "npm"
32
+ node-version: 22.x
33
+ cache: 'npm'
26
34
 
27
35
  - name: ๐Ÿ“ฅ Install Dependencies
28
36
  run: npm ci
@@ -54,7 +62,7 @@ jobs:
54
62
  strategy:
55
63
  matrix:
56
64
  os: [ubuntu-latest, windows-latest, macos-latest]
57
- node-version: [18.x, 20.x]
65
+ node-version: [18.x, 22.x]
58
66
  fail-fast: false
59
67
 
60
68
  steps:
@@ -64,7 +72,7 @@ jobs:
64
72
  uses: actions/setup-node@v3
65
73
  with:
66
74
  node-version: ${{ matrix.node-version }}
67
- cache: "npm"
75
+ cache: 'npm'
68
76
 
69
77
  - name: ๐Ÿ“ฅ Download Build
70
78
  uses: actions/download-artifact@v3
@@ -78,20 +86,24 @@ jobs:
78
86
  - name: ๐Ÿงช Run Core Tests
79
87
  run: npm test
80
88
  env:
81
- TEST_PROXY: ""
89
+ CI_HB_HEADLESS_TOKEN: ${{ secrets.HEADLESS_TEST_TOKEN }}
82
90
 
83
91
  - name: ๐ŸŒ Run Proxy Tests (Optional)
84
92
  if: always()
85
93
  continue-on-error: true
86
94
  run: npm test
87
95
  env:
88
- TEST_PROXY: "1"
96
+ CI_HB_PROXY: '1'
97
+ CI_HB_HEADLESS_TOKEN: ${{ secrets.HEADLESS_TEST_TOKEN }}
89
98
 
90
99
  publish:
91
- needs: build
100
+ needs: [build, test]
92
101
  name: ๐Ÿ“ข Publish Build
93
102
  if: github.event_name != 'pull_request'
94
103
  runs-on: ubuntu-latest
104
+ permissions:
105
+ contents: write
106
+ pull-requests: write
95
107
  steps:
96
108
  - uses: actions/checkout@v3
97
109
 
@@ -106,19 +118,29 @@ jobs:
106
118
  mv src/build.js src/index.js
107
119
  echo "โœจ Build prepared for publishing"
108
120
 
109
- - name: ๐Ÿš€ Commit and Push
121
+ - name: ๐Ÿš€ Create Pull Request
110
122
  run: |
111
123
  git config --global user.name 'github-actions[bot]'
112
124
  git config --global user.email 'github-actions[bot]@users.noreply.github.com'
113
125
 
126
+ BRANCH_NAME="bot/update-haxball-$(date +%Y%m%d-%H%M%S)"
127
+ git checkout -b "$BRANCH_NAME"
128
+
114
129
  if [[ -n "$(git status --porcelain)" ]]; then
115
130
  git add src/index.js
116
- git commit -m "๐Ÿค– Update Haxball.JS Build (${{ needs.build.outputs.hash }})
117
-
118
- ๐Ÿ”„ Auto-generated by GitHub Actions
119
- ๐Ÿท๏ธ Build Hash: ${{ needs.build.outputs.hash }}
120
- โšก Includes latest Haxball updates"
121
- git push
131
+ git commit -m "๐Ÿค– Update Haxball Headless (Build: ${{ needs.build.outputs.hash }})"
132
+ git push origin "$BRANCH_NAME"
133
+
134
+ gh pr create \
135
+ --title "๐Ÿค– Update Haxball Headless (Build: ${{ needs.build.outputs.hash }})" \
136
+ --body "๐Ÿ”„ Auto-generated by GitHub Actions
137
+
138
+ ๐Ÿท๏ธ Build Hash: ${{ needs.build.outputs.hash }}
139
+ โšก Includes latest Haxball Headless updates" \
140
+ --base main \
141
+ --head "$BRANCH_NAME"
122
142
  else
123
- echo "๐Ÿ“ No changes to commit"
143
+ echo "๐Ÿ“ No changes to commit, build is up-to-date. ๐Ÿ’ซ"
124
144
  fi
145
+ env:
146
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -15,9 +15,9 @@ jobs:
15
15
  - name: ๐ŸŸข Setup Node.js
16
16
  uses: actions/setup-node@v3
17
17
  with:
18
- node-version: 20.x
18
+ node-version: 22.x
19
19
  registry-url: https://registry.npmjs.org
20
- cache: "npm"
20
+ cache: 'npm'
21
21
 
22
22
  - name: ๐Ÿ“ฅ Install Dependencies
23
23
  run: npm ci
@@ -0,0 +1,6 @@
1
+ **/.git
2
+ **/.svn
3
+ **/.hg
4
+ **/node_modules
5
+
6
+ src/**/*.js
package/.prettierrc ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "printWidth": 80,
3
+ "tabWidth": 2,
4
+ "singleQuote": true,
5
+ "trailingComma": "es5"
6
+ }
@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
17
17
  Examples of behavior that contributes to a positive environment for our
18
18
  community include:
19
19
 
20
- * Demonstrating empathy and kindness toward other people
21
- * Being respectful of differing opinions, viewpoints, and experiences
22
- * Giving and gracefully accepting constructive feedback
23
- * Accepting responsibility and apologizing to those affected by our mistakes,
20
+ - Demonstrating empathy and kindness toward other people
21
+ - Being respectful of differing opinions, viewpoints, and experiences
22
+ - Giving and gracefully accepting constructive feedback
23
+ - Accepting responsibility and apologizing to those affected by our mistakes,
24
24
  and learning from the experience
25
- * Focusing on what is best not just for us as individuals, but for the
25
+ - Focusing on what is best not just for us as individuals, but for the
26
26
  overall community
27
27
 
28
28
  Examples of unacceptable behavior include:
29
29
 
30
- * The use of sexualized language or imagery, and sexual attention or
30
+ - The use of sexualized language or imagery, and sexual attention or
31
31
  advances of any kind
32
- * Trolling, insulting or derogatory comments, and personal or political attacks
33
- * Public or private harassment
34
- * Publishing others' private information, such as a physical or email
32
+ - Trolling, insulting or derogatory comments, and personal or political attacks
33
+ - Public or private harassment
34
+ - Publishing others' private information, such as a physical or email
35
35
  address, without their explicit permission
36
- * Other conduct which could reasonably be considered inappropriate in a
36
+ - Other conduct which could reasonably be considered inappropriate in a
37
37
  professional setting
38
38
 
39
39
  ## Enforcement Responsibilities
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
106
106
  ### 4. Permanent Ban
107
107
 
108
108
  **Community Impact**: Demonstrating a pattern of violation of community
109
- standards, including sustained inappropriate behavior, harassment of an
109
+ standards, including sustained inappropriate behavior, harassment of an
110
110
  individual, or aggression toward or disparagement of classes of individuals.
111
111
 
112
112
  **Consequence**: A permanent ban from any sort of public interaction within
package/README.md CHANGED
@@ -32,19 +32,19 @@ npm install haxball.js
32
32
  #### Module Usage Example
33
33
 
34
34
  ```js
35
- const HaxballJS = require("haxball.js");
35
+ const HaxballJS = require('haxball.js');
36
36
 
37
37
  HaxballJS.then((HBInit) => {
38
38
  // Same as in Haxball Headless Host Documentation
39
39
  const room = HBInit({
40
- roomName: "Haxball.JS",
40
+ roomName: 'Haxball.JS',
41
41
  maxPlayers: 16,
42
42
  public: true,
43
43
  noPlayer: true,
44
- token: "YOUR_TOKEN_HERE", // Required
44
+ token: 'YOUR_TOKEN_HERE', // Required
45
45
  });
46
46
 
47
- room.setDefaultStadium("Big");
47
+ room.setDefaultStadium('Big');
48
48
  room.setScoreLimit(5);
49
49
  room.setTimeLimit(0);
50
50
 
@@ -72,19 +72,19 @@ HBInit({
72
72
  #### TypeScript Example
73
73
 
74
74
  ```js
75
- import HaxballJS from "haxball.js";
75
+ import HaxballJS from 'haxball.js';
76
76
 
77
77
  HaxballJS.then((HBInit) => {
78
78
  // Same as in Haxball Headless Host Documentation
79
79
  const room = HBInit({
80
- roomName: "Haxball.JS",
80
+ roomName: 'Haxball.JS',
81
81
  maxPlayers: 16,
82
82
  public: true,
83
83
  noPlayer: true,
84
- token: "YOUR_TOKEN_HERE", // Required
84
+ token: 'YOUR_TOKEN_HERE', // Required
85
85
  });
86
86
 
87
- room.setDefaultStadium("Big");
87
+ room.setDefaultStadium('Big');
88
88
  room.setScoreLimit(5);
89
89
  room.setTimeLimit(0);
90
90
 
@@ -144,8 +144,7 @@ bun index.ts
144
144
 
145
145
  - Make a fork of this repository
146
146
  - Clone to you machine and entry on respective paste
147
- - Make sure to update testing token on `test/room.js` with a valid one for Github Actions CI/CD (Important)
148
- - Create a branch from develop: `git checkout -b my-feature develop`
147
+ - Create a branch with your resource: `git checkout -b my-feature`
149
148
  - Commit your changes: `git commit -m 'feat: My new feature'`
150
149
  - Push your branch: `git push origin my-feature`
151
150
  - A green button will appear at the beginning of this repository
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haxball.js",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "A powerful library for interacting with the Haxball Headless API",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "@types/haxball-headless-browser": ">=0.3.0",
25
25
  "https-proxy-agent": "^7.0.5",
26
26
  "json5": "^2.2.3",
27
- "node-datachannel": "^0.23.0",
27
+ "node-datachannel": "^0.24.0",
28
28
  "pako": "^2.1.0",
29
29
  "ws": "^8.18.0",
30
30
  "xhr2": "^0.2.1"
@@ -1,13 +1,13 @@
1
- const fs = require("fs").promises;
2
- const path = require("path");
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
3
 
4
4
  async function nodeify() {
5
5
  try {
6
6
  // Fetch cache hash
7
- const hashResponse = await fetch("https://www.haxball.com/cache_hash.json");
7
+ const hashResponse = await fetch('https://www.haxball.com/cache_hash.json');
8
8
  if (!hashResponse.ok)
9
9
  throw new Error(`Failed to fetch hash: ${hashResponse.status}`);
10
- const hash = (await hashResponse.text()).replaceAll('"', "");
10
+ let hash = (await hashResponse.text()).replaceAll('"', '');
11
11
 
12
12
  // Fetch source
13
13
  const sourceUrl = `https://www.haxball.com/${hash}/__cache_static__/g/headless-min.js`;
@@ -16,11 +16,15 @@ async function nodeify() {
16
16
  throw new Error(`Failed to fetch source: ${sourceResponse.status}`);
17
17
  let source = await sourceResponse.text();
18
18
 
19
+ // Extract hash from source header comment
20
+ const hashMatch = source.match(/\/\*[\s\S]*?(\b[a-f0-9]{8}\b)/);
21
+ hash = hashMatch?.[1];
22
+
19
23
  // Process source code
20
24
  source = processSource(source);
21
25
 
22
26
  // Write output
23
- const outputPath = path.join(__dirname, "../src/build.js");
27
+ const outputPath = path.join(__dirname, '../src/build.js');
24
28
  await writeOutputFile(outputPath, source);
25
29
 
26
30
  console.log(`SUCCESS:${hash}`); // Special format for GitHub Actions
@@ -47,12 +51,12 @@ function processSource(source) {
47
51
 
48
52
  function removeWindowReferences(source) {
49
53
  const replacements = {
50
- "window.": "",
51
- "parent.": "",
52
- "document.": "",
53
- ".innerHTML": "",
54
- 'getElementById("roomlink")': "null",
55
- 'getElementById("recaptcha")': "null",
54
+ 'window.': '',
55
+ 'parent.': '',
56
+ 'document.': '',
57
+ '.innerHTML': '',
58
+ 'getElementById("roomlink")': 'null',
59
+ 'getElementById("recaptcha")': 'null',
56
60
  };
57
61
 
58
62
  return Object.entries(replacements).reduce(
@@ -64,7 +68,7 @@ function removeWindowReferences(source) {
64
68
  function applyRegexReplacements(source) {
65
69
  // HBInit replacement
66
70
  const hbInitMatch = source.match(/HBInit=.+?;/);
67
- if (!hbInitMatch) throw new Error("Failed to find HBInit pattern");
71
+ if (!hbInitMatch) throw new Error('Failed to find HBInit pattern');
68
72
  source = source.replace(
69
73
  hbInitMatch[0],
70
74
  `promiseResolve(${hbInitMatch[0].substring(7, hbInitMatch[0].length - 1)});`
@@ -72,7 +76,7 @@ function applyRegexReplacements(source) {
72
76
 
73
77
  // WebSocket replacement
74
78
  const wsMatch = source.match(/new WebSocket\([^)]+\);/);
75
- if (!wsMatch) throw new Error("Failed to find WebSocket pattern");
79
+ if (!wsMatch) throw new Error('Failed to find WebSocket pattern');
76
80
  source = source.replace(
77
81
  wsMatch[0],
78
82
  wsMatch[0].replace(
@@ -85,7 +89,7 @@ function applyRegexReplacements(source) {
85
89
  const wsErrorPattern =
86
90
  /([a-zA-Z]+)\.([a-zA-Z]+)\.onerror=function\(\){([a-zA-Z]+)\.([a-zA-Z]+)\(!0\)}/;
87
91
  const wsErrorMatch = source.match(wsErrorPattern);
88
- if (!wsErrorMatch) throw new Error("Failed to find WebSocket error handler");
92
+ if (!wsErrorMatch) throw new Error('Failed to find WebSocket error handler');
89
93
 
90
94
  const [fullMatch, objName, wsProperty, methodObj, methodName] = wsErrorMatch;
91
95
  const debugCode = `${objName}.${wsProperty}.onerror=function(err){${methodObj}.${methodName}(!0);debug && console.error(err)};`;
@@ -95,7 +99,7 @@ function applyRegexReplacements(source) {
95
99
  const recaptchaMatch = source.match(
96
100
  /case "recaptcha":([a-zA-Z]+)\(([^)]+)\)/
97
101
  );
98
- if (!recaptchaMatch) throw new Error("Failed to find Recaptcha pattern");
102
+ if (!recaptchaMatch) throw new Error('Failed to find Recaptcha pattern');
99
103
  source = source.replace(
100
104
  recaptchaMatch[0],
101
105
  'case "recaptcha":console.log(new Error("Invalid Token Provided!"))'
@@ -111,13 +115,13 @@ function addProxySupport(source) {
111
115
  const initMatch = source.match(initPattern);
112
116
 
113
117
  if (!initMatch) {
114
- throw new Error("Could not find initialization pattern for proxy support");
118
+ throw new Error('Could not find initialization pattern for proxy support');
115
119
  }
116
120
 
117
121
  // Get the RoomConfigLookup function name
118
122
  const configLookupMatch = source.match(/(\w+)\("noPlayer",/);
119
123
  if (!configLookupMatch) {
120
- throw new Error("Could not find RoomConfigLookup function");
124
+ throw new Error('Could not find RoomConfigLookup function');
121
125
  }
122
126
  const configFn = configLookupMatch[1];
123
127
 
@@ -168,7 +172,7 @@ const onHBLoaded = function (cb) {
168
172
 
169
173
  async function writeOutputFile(outputPath, content) {
170
174
  await fs.mkdir(path.dirname(outputPath), { recursive: true });
171
- await fs.writeFile(outputPath, content, "utf8");
175
+ await fs.writeFile(outputPath, content, 'utf8');
172
176
  }
173
177
 
174
178
  nodeify();
package/test/room.js CHANGED
@@ -5,26 +5,27 @@ function requireUncached(module) {
5
5
 
6
6
  const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
7
7
 
8
- const TOKEN = "thr1.AAAAAGd82uXE_qA2Ongrnw.6AWO8_UYHKA"; // Make sure update here before testing
9
- const PROXY = "http://1.1.1.1:2222"; // (Optional) http://ip:port
10
-
11
- describe("HBInit Tests", function () {
8
+ describe('HBInit Tests', function () {
12
9
  this.timeout(10000);
13
10
 
14
11
  beforeEach(async function () {
15
- await delay(2000);
12
+ await delay(5000);
16
13
  });
17
14
 
18
- it("should create room", function (done) {
15
+ (process.env.CI_HB_HEADLESS_TOKEN || process.env.TEST_HB_HEADLESS_TOKEN
16
+ ? it
17
+ : it.skip)('should create room', function (done) {
19
18
  this.timeout(30000);
20
- requireUncached("../src/build").then((HBInit) => {
21
- var room = HBInit({
22
- roomName: "Haxball.JS",
19
+ requireUncached('../src/build').then((HBInit) => {
20
+ let room = HBInit({
21
+ roomName: 'Haxball.JS',
23
22
  maxPlayers: 16,
24
23
  public: false,
25
24
  noPlayer: true,
26
25
  debug: true,
27
- token: TOKEN,
26
+ token:
27
+ process.env.CI_HB_HEADLESS_TOKEN ||
28
+ process.env.TEST_HB_HEADLESS_TOKEN, // Fallback for local testing
28
29
  });
29
30
 
30
31
  room.onRoomLink = function () {
@@ -34,19 +35,24 @@ describe("HBInit Tests", function () {
34
35
  });
35
36
 
36
37
  // Optional proxy test
37
- (process.env.TEST_PROXY ? it : it.skip)(
38
- "should create room (proxy)",
38
+ (process.env.CI_HB_PROXY || process.env.TEST_HB_PROXY ? it : it.skip)(
39
+ 'should create room (proxy)',
39
40
  function (done) {
40
41
  this.timeout(30000);
41
- requireUncached("../src/build").then((HBInit) => {
42
- var room = HBInit({
43
- roomName: "Haxball.JS",
42
+
43
+ if (process.env.CI_HB_PROXY == '1') return done(); // Skip since testing proxy on GitHub Actions is not practical, test this locally instead
44
+
45
+ requireUncached('../src/build').then((HBInit) => {
46
+ let room = HBInit({
47
+ roomName: 'Haxball.JS',
44
48
  maxPlayers: 16,
45
49
  public: false,
46
50
  noPlayer: true,
47
51
  debug: true,
48
- proxy: PROXY,
49
- token: TOKEN,
52
+ proxy: process.env.CI_HB_PROXY || process.env.TEST_HB_PROXY, // Fallback for local testing
53
+ token:
54
+ process.env.CI_HB_HEADLESS_TOKEN ||
55
+ process.env.TEST_HB_HEADLESS_TOKEN, // Fallback for local testing
50
56
  });
51
57
 
52
58
  room.onRoomLink = function () {
package/types/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import "haxball-headless-browser";
1
+ import 'haxball-headless-browser';
2
2
 
3
3
  interface RoomConfigObjectM extends RoomConfigObject {
4
- proxy?: string
5
- debug?: boolean
4
+ proxy?: string;
5
+ debug?: boolean;
6
6
  }
7
7
  export declare type Headless = (RoomConfig: RoomConfigObjectM) => RoomObject;
8
8
 
9
- declare const HaxballJS: Promise<Headless>
10
- export default HaxballJS
9
+ declare const HaxballJS: Promise<Headless>;
10
+ export default HaxballJS;