Skip to main content
This guide covers the day-to-day development workflow for working with bet365-re-js, from making changes to testing and debugging.

Quick Start Development Loop

The most efficient workflow for developing new transformations:
1

Set up automatic recompilation

Use watchexec to automatically run transformations when you save files:
watchexec -e js "touch mitmproxy/src/python/download-payload.py && \
node mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift.js \
mitmproxy/src/javascript/obfuscated-original.js \
mitmproxy/src/javascript/deobfuscated-output.js && \
node mitmproxy/src/javascript/pre-transform-code.js"
This watches for changes in any *.js file (except obfuscated-original.js and deobfuscated.js) and automatically recompiles.
2

Edit transformation scripts

Open your preferred editor and modify transformation scripts in:
mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift-*.js
Each time you save, watchexec automatically runs the transformation.
3

Check the output

Review the generated output:
code mitmproxy/src/javascript/deobfuscated-output.js
Or diff against expected output:
diff deobfuscated-output.js expected-output.js
This workflow eliminates the need to manually run the transformation command after every change, significantly speeding up development.

Project Structure

Understanding the project layout helps you navigate efficiently:
bet365-re-js/
├── mitmproxy/
│   └── src/
│       ├── python/
│       │   ├── main/
│       │   │   └── download-payload.py      # Main interception script
│       │   ├── save_obfuscated_code.py      # Save intercepted code
│       │   ├── requirements.txt             # Python dependencies
│       │   └── tests/                       # Python/Playwright tests
│       └── javascript/
│           ├── refactor-obfuscated-code-jscodeshift.js       # Entry point
│           ├── refactor-obfuscated-code-jscodeshift-*.js     # Transformations
│           ├── refactor-obfuscated-code-jscodeshift-*.test.js # Tests
│           ├── pre-transform-code.js        # Injected before deobfuscated code
│           ├── post-transform-code.js       # Injected after deobfuscated code
│           ├── obfuscated/                  # Historical obfuscated versions
│           ├── obfuscated-original.js       # Your working copy
│           └── deobfuscated-output.js       # Generated output
├── output/                                   # Intercepted files (gitignored)
├── chrome-profile/                          # Chrome user data (gitignored)
├── package.json                             # Node.js dependencies
├── mitmproxy.sh                             # Start proxy script
├── new-conda-environment.sh                 # Python env setup
└── python-dependencies.sh                   # Install Python deps

Common Development Tasks

Testing Your Changes

npm test
# Runs all Jest tests for transformation scripts

Adding a New Transformation

1

Create the transformation script

touch mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift-11.js
Template structure:
const transform = (ast, j) => {
  // Your transformation logic here
  return ast;
};

module.exports = transform;
2

Create a test file

touch mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift-11.test.js
Template:
const transform = require('./refactor-obfuscated-code-jscodeshift-11');
const testUtil = require('./refactor-obfuscated-code-jscodeshift-test-util');

describe('Transformation 11', () => {
  it('should handle new obfuscation pattern', () => {
    const input = `/* obfuscated code */`;
    const expected = `/* deobfuscated code */`;
    const result = testUtil.applyTransform(transform, input);
    expect(result).toBe(expected);
  });
});
3

Import into the chain

Edit refactor-obfuscated-code-jscodeshift-chained.js to include your transformation:
const transform11 = require('./refactor-obfuscated-code-jscodeshift-11');

// Add to the chain
ast = transform11(ast, j);
4

Test the change

npm test -- refactor-obfuscated-code-jscodeshift-11.test.js

Working with Obfuscated Code Versions

The project tracks multiple versions of bet365’s obfuscated code:
# List all saved versions
ls -lht mitmproxy/src/javascript/obfuscated/

# Compare two versions
diff -u mitmproxy/src/javascript/obfuscated/2024-01-15.js \
        mitmproxy/src/javascript/obfuscated/2024-02-01.js

# Test against a specific version
node mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift.js \
  mitmproxy/src/javascript/obfuscated/2024-01-15.js \
  test-output.js
Keeping historical versions helps ensure your transformations work across different obfuscation patterns and don’t introduce regressions.

Development Tools

AST Explorer

For prototyping transformations: https://astexplorer.net/
  1. Paste obfuscated JavaScript in the left pane
  2. Select Parser: recast or esprima
  3. Select Transform: jscodeshift
  4. Write your transformation in the bottom pane
  5. See results in real-time

JavaScript Formatter

For formatting obfuscated code: https://unminify.com/
This formatter handles comma operators particularly well, which bet365 uses extensively in their obfuscation.

Debugging Chrome Output

When running Chrome with --enable-logging --v=1, view console output without opening DevTools:
# View raw logs
tail -f ./chrome-profile/chrome_debug.log

# Filter for JSON output from injected code
tail -f ./chrome-profile/chrome_debug.log | \
  sed -En "s/.*inside.*\\]: (.*)\", source:  \(3\)/\1/p"
Opening DevTools triggers bet365’s anti-debugging measures. The tapeKeywords[27269]: "" value is set when DevTools is open, which may alter behavior.

Running the Full Pipeline

End-to-End Test

Test the complete interception and deobfuscation workflow:
1

Start mitmproxy

./mitmproxy.sh
2

Launch proxied browser

open -a "Google Chrome" --args \
  --proxy-server=http://localhost:8080 \
  --user-data-dir=$(pwd)/chrome-profile
3

Navigate and verify

  1. Go to https://www.bet365.com
  2. Check mitmproxy logs for “Intercepting response”
  3. Verify files appear in output/
  4. Check that -sent- files contain deobfuscated code

Debugging Failed Deobfuscation

If the deobfuscation fails:
ls -lht output/*-received-*.js | head -5
head -50 output/[latest]-received-0.js
# Verify the obfuscated code was intercepted correctly

Best Practices

Code Organization

Keep transformations focused: Each refactor-obfuscated-code-jscodeshift-*.js file should handle one specific obfuscation pattern. This makes debugging easier.

Version Control

# Before making changes, save the current obfuscated version
cp mitmproxy/src/javascript/obfuscated-new-raw.js \
   mitmproxy/src/javascript/obfuscated/$(date +%Y-%m-%d).js

# Commit with descriptive messages
git add mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift-11.js
git commit -m "Add transformation for new string encoding pattern"

Testing Strategy

  1. Unit tests - Test individual transformations with *.test.js files
  2. Integration tests - Test the full transformation chain with real obfuscated samples
  3. Regression tests - Test against historical obfuscated versions
# Run against all historical versions
for file in mitmproxy/src/javascript/obfuscated/*.js; do
  echo "Testing $file"
  node mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift.js \
    "$file" \
    "test-output-$(basename $file)" && echo "✓ PASS" || echo "✗ FAIL"
done

Performance Optimization

Transformations run on every intercepted request in real-time. Keep them efficient to avoid slowing down the browser experience.
Profile transformation performance:
time node mitmproxy/src/javascript/refactor-obfuscated-code-jscodeshift.js \
  mitmproxy/src/javascript/obfuscated-original.js \
  /dev/null

Continuous Integration (Future)

The project plans to implement CI/CD to:
  • Automatically detect when bet365 updates their obfuscated code
  • Run regression tests against new versions
  • Alert when transformations break
  • Maintain a backup deobfuscation script
This is a planned feature mentioned in the README but not yet implemented.

Troubleshooting Common Issues

watchexec not found

# macOS
brew install watchexec

# Linux
sudo apt install watchexec  # Debian/Ubuntu
# or check your distribution's package manager

Node version mismatch

nvm use
# Automatically switches to the version in .nvmrc (v22.15.0)

Transformation errors

If you see “SyntaxError” in the output:
  1. Check if the input file is valid JavaScript
  2. Verify you’re using the correct jscodeshift API
  3. Test in AST Explorer first
  4. Add error handling to your transformation

Python/Node environment conflicts

Ensure you’re in the correct environments:
# Check Python env
conda env list  # Should show * next to bet365-re-js

# Check Node version
node --version  # Should be v22.15.0

Next Steps

  • Review existing transformation scripts in mitmproxy/src/javascript/
  • Experiment with AST Explorer to understand code patterns
  • Try intercepting live traffic from bet365
  • Contribute new transformations when obfuscation patterns change

Build docs developers (and LLMs) love