summaryrefslogtreecommitdiff
path: root/src/main/resources/META-INF/resources/posts/commentBox.js
blob: 96605f9fc31b3f0c77c0a9eebfa5074ae18ae9c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
document.addEventListener('DOMContentLoaded', () => {
  const messageEncoder = new TextEncoder();
  const hashcashAttemptBatchSize = 1000;

  const acceptableHash = (hash) => hash[0] === 0 && hash[1] === 0;

  const checkSalt = (message, salt, thenC, elseC) => {
    const saltedMessage = `Hashcash-Salt: ${salt}\n\n${message}`;
    const encodedSaltedMessage = messageEncoder.encode(saltedMessage);

    crypto.subtle.digest('SHA-256', encodedSaltedMessage).then((hashBuf) => {
      if (acceptableHash(new Uint8Array(hashBuf))) {
        thenC();
      } else {
        elseC();
      }
    });
  };

  const commentForms = document.getElementsByClassName('comment-form');
  for (const commentForm of commentForms) {
    const hashcashSaltInput = commentForm.querySelector('input[name=hashcash-salt]');
    const messageTextarea = commentForm.querySelector('textarea[name=message]');
    const submitButton = commentForm.querySelector('input[type=submit]');

    let salt = 0;
    const tryHashcash = () => {
      checkSalt(messageTextarea.value, salt, () => {
        hashcashSaltInput.value = salt;
        console.log(`hashcash ok ${salt}`);
        submitButton.toggleAttribute('disabled');
        commentForm.submit();
      }, () => {
        ++salt;
        if (salt % hashcashAttemptBatchSize === 0) {
          console.log(`hashcash fail ${salt}, retrying`);
        }
        setTimeout(tryHashcash, 0);
      });
    };

    commentForm.addEventListener(
        'submit',
        (event) => {
          event.preventDefault();
          submitButton.setAttribute('disabled', 'disabled');
          setTimeout(tryHashcash, 0);
        });
  }
});