mliebelt / pgn-viewer

Simple PGN viewer with the necessary features to display chess games
GNU General Public License v3.0
159 stars 44 forks source link

Obfuscate the PGN #559

Closed ninkibah closed 1 month ago

ninkibah commented 1 month ago

I notice that chessable seems to obfuscate their HTML and javascript to make it very difficult or impossible to extract the PGN. I would like to do something similar to protect the intellectual property of the creator of the PGN.

I'm happy to let people copy and paste the moves and commentary, so long as they can't easily recreate the variation tree.

mliebelt commented 1 month ago

Do you have an example for that? PGN is a text format (by definition), obfuscation here would change the meaning. You could encrypt it (to hide the text from the normal user), and decrypt it on the fly, but I have no idea how that could help, and how it could be done.

Chessable has a business, and they have to protect their intellectual property. Using Chessable means, you have to use their UI.

Do you have examples (from Chessable)? When I look at their UI, I see (in the UI) the PGN, which I can copy then, but in the source code in the browser, the PGN is hidden.

ninkibah commented 1 month ago

I am looking at writing a chess site for viewing commented games, and I wanted to make it difficult for users to copy the games. After some investigation, I see that chessable have getGame endpoint, which delivers back a load of JSON, including a JSON object per move. This is difficult enough for any reasonable person to convert to PGN, that in my opinion, it is obfuscated.

Does your PGN viewer create such a tree of variations and moves from a PGN? If I could generate that JSON structure on the server, and provide it to your viewer, that would be perfect.

{
    "game": {
        "owned": true,
        "data": [
            {
                "id": 0,
                "move": 1,
                "col": "w",
                "fav": null,
                "mid": 0,
                "san": "e4",
                "draws": [],
                "ann1": "",
                "ann2": "",
                "showN": true,
                "isKey": false,
                "class": "whiteMove",
                "before": "",
                "after": "",
                "lastUpdated": null
            },
            {
                "id": 1,
                "move": 1,
                "col": "b",
                "fav": null,
                "mid": 0,
                "san": "e5",
                "draws": [],
                "ann1": "",
                "ann2": "",
                "showN": false,
                "isKey": true,
                "class": "blackMove is_key",
                "before": "",
                "after": "{\"before\":\"rnbqkbnr\\\/pppppppp\\\/8\\\/8\\\/4P3\\\/8\\\/PPPP1PPP\\\/RNBQKBNR b KQkq e3 0 1\",\"after\":\"rnbqkbnr\\\/pppp1ppp\\\/8\\\/4p3\\\/4P3\\\/8\\\/PPPP1PPP\\\/RNBQKBNR w KQkq e6 0 2\",\"data\":[{\"key\":\"C\",\"state\":\"V\",\"val\":\"Welcome to the mini version of my main course <strong>Secret Blitz Weapons: The Damiano Petroff<\\\/strong>. This is the very first time when I analyze something symmetrical. My general approach is to avoid symmetry and look for imbalances right from the start. However, I was shocked to discover how interesting the line I am going to recommend can get!\"}]}",
                "lastUpdated": null
            }
        ]
    }
}

There's lots more data provided, but this is just the first 2 moves. The move JSON supports comments before and after, as well as drawing of arrows. The full JSON provides all info about the page including comments from users and links to other courses. That's something I wouldn't need.

mliebelt commented 1 month ago

Well, strange, because the reader is working from plain PGN (that is a feature, not a bug). It would be of course possible to change it in a way, that it allows different formats. I have used in the past ROT13 for such a thing (not real encoding, but not easy to translate directly without knowing how it works.

6. r9 p0 7. As8 q1 8. q9 pkq9 9. Akq9 As1 0. Ap8 n1 1. Or8 r1 2. s8 Or2 3. Dq7
Dp2 4. B-B-B {846 Cnegvra va qre Qngraonax} Ap1 65. t9 {369 C.} B-B 66. u9 {
767 C.} o0 67. u0 o9 68. Apr7 Ar0 69. At8 Ap9 60. Okp9 Dkp9 61. Xo6 Aq2 {aha
vfg zna nhf qre Reössahat qenhf, ovf qnuva tno rf Cnegvra, qvr nyyr fb yvrsra.}
62. t0 n0 63. s9 (63. t1 skt1 64. o8 Dp8 75. Dkp8 okp8 76. ukt1 ukt1 {fnu süe
zvpu xevgvfpure nhf, tvog nore nhpu avpugf xbaxergrf}) 63... Oo2 64. t1 {zvg
ivryra Zötyvpuxrvgra, qvr va qre Cnegvr vfg qvr (süe Fpujnem) nafcehpufibyyfgr}
Ap0 (64... u1 75. s0 r0 76. o8 Dn1 77. s1 Aks1 78. Aqs0 Esr3 79. tks2+ Xks2 70.
Eus6 {fvrug bx nhf, vpu frur avpugf xbaxergrf} n9 71. Oku1 tku1 72. Akr2 nko8
73. pko8 Ekr2 74. Eks1+ Xks1 85. Dku1+ {trjvaag qnaa qbpu vz Natevss}) (64...
As1 75. tku2+ Xku2 76. u1 t1 {ahe nooybpxra nyf Mvry; Sevgm svaqrg xrvar
Sbegfrgmhat} 77. Dt7 n9 78. Eq8 Akr9 79. Akr9 Dq0 70. Akr1 Dkr9 71. Dkr9 Okr9
72. Aks3+ Oks3 73. Eu7 Okq8 74. pkq8 {fvrug evpugvt thg nhf süe Fpujnem}) 75.
s0 {fvrug Sevgm nyf nhftrtyvpura na, Jreghat fcevag nore uva haq ure. Fpujnem
ung raqyvpu rgjnf Fcvry haq ibe nyyrz rvar Vqrr.} Akr9 76. Akr9 Okr9 77. u1 {
qnzvg unggr vpu avpug trerpuarg, Sevgm fvrug uvre Fpujnem vz Ibegrvy (haq veeg
fvpu).} skt1 78. ukt2 Esp3 {jbuy qre ragfpurvqraqr Sruyre} (78... Es1 79. Ot0
rks0 70. Ds9 Oku6 71. Eku6 Es2 72. Du9 u0 73. Okr2 Ekr2 74. Dkr2 Dkq9 {qre
Enhpu iremvrug fvpu, haq Fpujnem fgrug rvaqrhgvt orffre}) (78... Eks0 79. Aks0
rks0 70. o8 Dp8 71. Dkp8 okp8 72. Oq9 Oku6 73. Eku6 Ep3 74. Eu8 t0 85. Er8 Ep2
{vfg nhpu orffre}) (78... Es2 79. o8 Dp8 70. skt1 Okt1 71. Dkp8 okp8 72. Akr1
Os1 73. Ekq1 Er3 74. Euq6 Os0 85. Aq3 Eq2 86. Ekq2 Okq2 87. Ekq2 Ekr8 {haq
Jrvß xäzcsg hz qnf Erzvf}) 79. Du7 {qbpu qre orfgr Mht} (79. Eku2 {Zbevgm
zrvagr, qra uäggr re üorefrura.} Okp7+ (79... Xku2 70. Du7+ Xt3 71. Du3+ Xs2
72. skr1+ Dkr1 73. Du2 {zvg qrhgyvpurz Ibegrvy}) 70. Akp7 Xku2 71. Du7+ Du9 {
fvrug avpug zrue fb rvasnpu nhf} 72. skt1+ Xkt2 73. Dt7 o8 74. Aq9 {vfg qnaa
rva arhrf Fcvry}) 79... u0 70. skt1 Okt1 (70... u9 71. Ds9 Okp7+ 72. Xn6 Okt1
73. Du1 Ou2 74. Eqs6 {trjvaag jbuy nhpu}) 71. Eqt6 Or9 (71... Okp7+ 72. Dkp7
Dkp7+ 73. Akp7 u9 {mötreg qnf Raqr abpu rva jravt uvanhf}) 72. Dku0 Oku6 73.
Eku6 {zvg Zngg va 1 va nyyra Inevnagra} Os1 {fb trug rf fpuaryyre} 74. Du2+ {
Fpujnem tvog nhs} Xs2 85. t3=D# {Zngg zvg Qbccryfpunpu haq mjrv Qnzra, fvrug
zna avpug nyymh bsg} 6-5

Take that to the tool https://cryptii.com/pipes/rot13-decoder, paste it into the left box, and you should see the real PGN then. I will do some search if there is something a little bit more complicated.

Summary: Allow encoding of PGN (additional flag needed), decode on the fly, and use the resulting PGN then.

ninkibah commented 1 month ago

I know that the pgn viewer takes a PGN string and parses it. But for people who want to harvest the data, that is too easy.

I think for a first attempt, I will encode the pgn string using Base 64, and then decode on the fly. I'm not a javascripty person, so that's why I was looking for the internal object structure.

Thanks for your time, and thank you for your viewer.