Skip to content

Instantly share code, notes, and snippets.

@pgaskin
Last active January 11, 2026 11:13
Show Gist options
  • Select an option

  • Save pgaskin/b02ba7c2bf3eeb722852c216c69e09c3 to your computer and use it in GitHub Desktop.

Select an option

Save pgaskin/b02ba7c2bf3eeb722852c216c69e09c3 to your computer and use it in GitHub Desktop.
// Command aftership-order-status extracts the full status information from an
// aftership order-status webpage.
package main
import (
"bytes"
"encoding/json"
"errors"
"math/bits"
"os"
"slices"
"strings"
"unicode/utf16"
"unicode/utf8"
"unsafe"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
// https://XXXXX.aftership.com/order-status?XXXXX
// (decompress=>JSON.parse(decompress(JSON.parse(document.getElementById('__NEXT_DATA__').textContent).props.initialProps.initialData.initialState)).atoms.order.order)(function(r){let t=String.fromCharCode,e=Error("invalid"),h=0,o=0,f=0,i=t=>{let i=0;for(let l=0;l<t;l++){if(0==f){if(h>=r.length)throw e;f=32768,o=r.charCodeAt(h++)}o&f&&(i|=1<<l),f>>=1}return i},l,n=[],a="";for(;;){let r,h=n.length,o=i(32-Math.clz32(3+h));if(2==o)return a;if(o>2){if(o-=3,!l||o>h)throw e;r=o<h?n[o]:l+l.charAt(0)}else r=t(i(o?16:8)),n.push(r);l&&n.push(l+r.charAt(0)),l=r,a+=r}})
func main() {
doc, err := html.Parse(os.Stdin)
if err != nil {
panic(err)
}
var data bytes.Buffer
for child := range doc.Descendants() {
if child.Type == html.ElementNode && child.DataAtom == atom.Script && slices.ContainsFunc(child.Attr, func(a html.Attribute) bool {
return a.Key == "id" && a.Val == "__NEXT_DATA__"
}) {
for n := range child.Descendants() {
if n.Type == html.TextNode {
data.WriteString(n.Data)
}
}
break
}
}
var obj struct {
Props struct {
InitialProps struct {
InitialData struct {
InitialState json.RawMessage `json:"initialState"`
} `json:"initialData"`
} `json:"initialProps"`
} `json:"props"`
}
if err := json.NewDecoder(&data).Decode(&obj); err != nil {
panic(err)
}
s, err := unquote(nil, []byte(obj.Props.InitialProps.InitialData.InitialState))
if err != nil {
panic(err)
}
d, err := decompress(nil, s)
if err != nil {
panic(err)
}
var obj1 struct {
Atoms struct {
Order struct {
Order json.RawMessage `json:"order"`
} `json:"order"`
} `json:"atoms"`
}
if err := json.NewDecoder(strings.NewReader(string(utf16.Decode(d)))).Decode(&obj1); err != nil {
panic(err)
}
f := new(bytes.Buffer)
if err := json.Indent(f, []byte(obj1.Atoms.Order.Order), "", " "); err != nil {
panic(err)
}
e := json.NewEncoder(os.Stdout)
e.SetIndent("", " ")
e.SetEscapeHTML(false)
if err := e.Encode(obj1.Atoms.Order.Order); err != nil {
panic(err)
}
}
// https://gist.github.com/pgaskin/1d2f1c7f5002670432247dd5adf85557
// decompress decompresses a lzstring-compressed byte sequence from a slice of
// bytes or utf-16 code units, appending the result into an slice of utf-16 code
// units. To decode the result, use string(utf16.Decode(dst)).
func decompress[T byte | uint16](dst []uint16, src []T) ([]uint16, error) {
var (
dat uint32
bit uint32
)
ubits := func(bits int) (res uint32, ok bool) {
// interpret src as a big-endian bitstream, and read a little-endian uint from it
for i := range bits {
if bit == 0 {
if len(src) == 0 {
return res, false
}
bit = 1 << (uint(unsafe.Sizeof(src[0])*8) - 1)
dat = uint32(src[0])
src = src[1:]
}
if dat&bit != 0 {
res |= 1 << i
}
bit >>= 1 // msb to lsb
}
return res, true
}
var (
last uint32 // last chunk start index
dict [][2]uint32
)
for {
dictSize := uint32(len(dict))
op, ok := ubits(bits.Len32(3 + dictSize))
if !ok {
return dst, errors.New("unexpected end of stream")
}
if op == 2 {
return dst, nil
}
chunk := uint32(len(dst)) // current chunk start index
if op > 2 {
idx := op - 3
if dictSize == 0 {
return dst, errors.New("first packet must be a literal")
}
if idx > dictSize {
return dst, errors.New("dictionary index out of range")
}
if idx == dictSize {
dst = append(dst, dst[last:]...)
dst = append(dst, dst[last])
} else {
dst = append(dst, dst[dict[idx][0]:dict[idx][1]]...)
}
} else {
bits := [...]int{
0: 8,
1: 16,
}[op]
lit, ok := ubits(bits)
if !ok {
return dst, errors.New("unexpected end of stream")
}
dst = append(dst, uint16(lit))
dict = append(dict, [2]uint32{chunk, chunk + 1})
}
if dictSize != 0 {
dict = append(dict, [2]uint32{last, chunk + 1})
}
last = chunk
}
}
// unquote unquotes a valid JSON string as a series of UTF-16 code units. Any
// junk after the end of the string is ignored. This is roughly equivalent to
// the following JS:
//
// function unquote(s) {
// s = JSON.parse(s)
// return Array(s.length).keys().map(i => s.charCodeAt(i)).toArray()
// }
//
// Unlike the usual Go strings and JSON libraries, this will split high UTF-8
// characters into the UTF-16 surrogate pairs, and it will preserve invalid
// surrogate pairs as their raw hex values.
//
// This is intended for use when parsing and decompressing raw lzstrings
// serialized as JSON, i.e.:
//
// JSON.stringify(LZString.compress("whatever"))
func unquote[T string | []byte](dst []uint16, src T) ([]uint16, error) {
if len(src) == 0 || src[0] != '"' {
return dst, errors.New("json string missing start quote")
}
src = src[1:]
for {
if len(src) == 0 {
return dst, errors.New("json string missing end quote")
}
r, rn := utf8.DecodeRuneInString(string(src[:min(len(src), 4)]))
if r == utf8.RuneError {
return dst, errors.New("json is not valid utf-8")
}
src = src[rn:]
switch {
case r == '"':
return dst, nil
case r == '\\':
if len(src) == 0 {
return dst, errors.New("unexpected eof in json escape")
}
e := src[0]
src = src[1:]
switch e {
case '"', '\\', '/':
dst = append(dst, uint16(e))
case 'b':
dst = append(dst, '\b')
case 'f':
dst = append(dst, '\f')
case 'n':
dst = append(dst, '\n')
case 'r':
dst = append(dst, '\r')
case 't':
dst = append(dst, '\t')
case 'u':
if len(src) < 4 {
return dst, errors.New("invalid json unicode escape")
}
var v uint16
for _, c := range []byte(src[:4]) {
switch {
case '0' <= c && c <= '9':
c = c - '0'
case 'a' <= c && c <= 'f':
c = 10 + c - 'a'
case 'A' <= c && c <= 'F':
c = 10 + c - 'A'
default:
return dst, errors.New("invalid json unicode escape")
}
v = v*16 + uint16(c)
}
src = src[4:]
dst = append(dst, v)
default:
return dst, errors.New("invalid json escape")
}
case r >= 1<<16:
// would be encoded as a surrogate pair, so split it into the two code units
dst = append(dst, uint16(0xd800+((r-1<<16)>>10)&0x3ff), uint16(0xdc00+(r-1<<16)&0x3ff))
default:
dst = append(dst, uint16(r))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment