# I am the Watcher. I am your guide through this vast new twtiverse.
# 
# Usage:
#     https://watcher.sour.is/api/plain/users              View list of users and latest twt date.
#     https://watcher.sour.is/api/plain/twt                View all twts.
#     https://watcher.sour.is/api/plain/mentions?uri=:uri  View all mentions for uri.
#     https://watcher.sour.is/api/plain/conv/:hash         View all twts for a conversation subject.
# 
# Options:
#     uri     Filter to show a specific users twts.
#     offset  Start index for quey.
#     limit   Count of items to return (going back in time).
# 
# twt range = 1 1188
# self = https://watcher.sour.is?uri=https://dev.txt.sour.is/user/xuu/twtxt.txt&offset=515
# next = https://watcher.sour.is?uri=https://dev.txt.sour.is/user/xuu/twtxt.txt&offset=615
# prev = https://watcher.sour.is?uri=https://dev.txt.sour.is/user/xuu/twtxt.txt&offset=415
@prologic yeah. For commercial use even. Just need to put an attribution note in the project README
@prologic +1
I set mine to 4096
@prologic if we do adopt this one it is CC-BY from twitter. https://twemoji.twitter.com
@lyse Excellent use of old denim, and also excellent use of long-form twt!
I think i would like a display mode that sorts yarns by last twt in yarn and displays only the last twt with the first in the heading if its more than one in length.
@novaburst I doubt there will ever be a 2.0 ... It may end up like java and they strip off the 1.
@ullarah works for me! A tricky bitmight be if it splits within a codeblock so markdown can't parse
@prologic



#!/bin/sh

# Validate environment
if ! command -v msgbus > /dev/null; then
    printf "missing msgbus command. Use:  go install git.mills.io/prologic/msgbus/cmd/msgbus@latest"
    exit 1
fi

if ! command -v salty > /dev/null; then
    printf "missing salty command. Use:  go install go.mills.io/salty/cmd/salty@latest"
    exit 1
fi

if ! command -v salty-keygen > /dev/null; then
    printf "missing salty-keygen command. Use:  go install go.mills.io/salty/cmd/salty-keygen@latest"
    exit 1
fi

if [ -z "$SALTY_IDENTITY" ]; then
    export SALTY_IDENTITY="$HOME/.config/salty/$USER.key"
fi

get_user () {
    user=$(grep user: "$SALTY_IDENTITY" | awk '{print $3}')
    if [ -z "$user" ]; then
        user="$USER"
    fi
    echo "$user"
}

stream () {
    if [ -z "$SALTY_IDENTITY" ]; then
        echo "SALTY_IDENTITY not set"
        exit 2
    fi

    jq -r '.payload' | base64 -d | salty -i "$SALTY_IDENTITY" -d
}

lookup () {
    if [ $# -lt 1 ]; then
    printf "Usage: %s nick@domain\\n" "$(basename "$0")"
    exit 1
    fi

    user="$1"
    nick="$(echo "$user" | awk -F@ '{ print $1 }')"
    domain="$(echo "$user" | awk -F@ '{ print $2 }')"

    curl -qsSL "https://$domain/.well-known/salty/${nick}.json"
}

readmsgs () {
    topic="$1"

    if [ -z "$topic" ]; then
        topic=$(get_user)
    fi

    export SALTY_IDENTITY="$HOME/.config/salty/$topic.key"
    if [ ! -f "$SALTY_IDENTITY" ]; then
        echo "identity file missing for user $topic" >&2
        exit 1
    fi

    msgbus sub "$topic" "$0"
}

sendmsg () {
    if [ $# -lt 2 ]; then
        printf "Usage: %s nick@domain.tld <message>\\n" "$(basename "$0")"
        exit 0
    fi

    if [ -z "$SALTY_IDENTITY" ]; then
        echo "SALTY_IDENTITY not set"
        exit 2
    fi

    user="$1"
    message="$2"

    salty_json="$(mktemp /tmp/salty.XXXXXX)"

    lookup "$user" > "$salty_json"

    endpoint="$(jq -r '.endpoint' < "$salty_json")"
    topic="$(jq -r '.topic' < "$salty_json")"
    key="$(jq -r '.key' < "$salty_json")"

    rm "$salty_json"

    message="[$(date +%FT%TZ)] <$(get_user)> $message"

    echo "$message" \\
        | salty -i "$SALTY_IDENTITY" -r "$key" \\
        | msgbus -u "$endpoint" pub "$topic"
}

make_user () {
    mkdir -p "$HOME/.config/salty"

    if [ $# -lt 1 ]; then
        user=$USER
    else
        user=$1
    fi

    identity_file="$HOME/.config/salty/$user.key"

    if [ -f "$identity_file" ]; then
        printf "user key exists!"
        exit 1
    fi

    # Check for msgbus env.. probably can make it fallback to looking for a config file?
    if [ -z "$MSGBUS_URI" ]; then
        printf "missing MSGBUS_URI in environment"
        exit 1
    fi


    salty-keygen -o "$identity_file"
    echo "# user: $user" >> "$identity_file"

    pubkey=$(grep key: "$identity_file" | awk '{print $4}')

    cat <<- EOF
Create this file in your webserver well-known folder. https://hostname.tld/.well-known/salty/$user.json

{
  "endpoint": "$MSGBUS_URI",
  "topic": "$user",
  "key": "$pubkey"
}

EOF
}

# check if streaming
if [ ! -t 1 ]; then
    stream
    exit 0
fi

# Show Help
if [ $# -lt 1 ]; then
    printf "Commands: send read lookup"
    exit 0
fi


CMD=$1
shift

case $CMD in
    send)
        sendmsg "$@"
    ;;
    read)
        readmsgs "$@"
    ;;
    lookup)
        lookup "$@"
    ;;
    make-user)
        make_user "$@"
    ;;
esac
@prologic



#!/bin/sh

# Validate environment
if ! command -v msgbus > /dev/null; then
    printf "missing msgbus command. Use:  go install git.mills.io/prologic/msgbus/cmd/msgbus@latest"
    exit 1
fi

if ! command -v salty > /dev/null; then
    printf "missing salty command. Use:  go install go.mills.io/salty/cmd/salty@latest"
    exit 1
fi

if ! command -v salty-keygen > /dev/null; then
    printf "missing salty-keygen command. Use:  go install go.mills.io/salty/cmd/salty-keygen@latest"
    exit 1
fi

if [ -z "$SALTY_IDENTITY" ]; then
    export SALTY_IDENTITY="$HOME/.config/salty/$USER.key"
fi

get_user () {
    user=$(grep user: "$SALTY_IDENTITY" | awk '{print $3}')
    if [ -z "$user" ]; then
        user="$USER"
    fi
    echo "$user"
}

stream () {
    if [ -z "$SALTY_IDENTITY" ]; then
        echo "SALTY_IDENTITY not set"
        exit 2
    fi

    jq -r '.payload' | base64 -d | salty -i "$SALTY_IDENTITY" -d
}

lookup () {
    if [ $# -lt 1 ]; then
    printf "Usage: %s nick@domain\n" "$(basename "$0")"
    exit 1
    fi

    user="$1"
    nick="$(echo "$user" | awk -F@ '{ print $1 }')"
    domain="$(echo "$user" | awk -F@ '{ print $2 }')"

    curl -qsSL "https://$domain/.well-known/salty/${nick}.json"
}

readmsgs () {
    topic="$1"

    if [ -z "$topic" ]; then
        topic=$(get_user)
    fi

    export SALTY_IDENTITY="$HOME/.config/salty/$topic.key"
    if [ ! -f "$SALTY_IDENTITY" ]; then
        echo "identity file missing for user $topic" >&2
        exit 1
    fi

    msgbus sub "$topic" "$0"
}

sendmsg () {
    if [ $# -lt 2 ]; then
        printf "Usage: %s nick@domain.tld <message>\n" "$(basename "$0")"
        exit 0
    fi

    if [ -z "$SALTY_IDENTITY" ]; then
        echo "SALTY_IDENTITY not set"
        exit 2
    fi

    user="$1"
    message="$2"

    salty_json="$(mktemp /tmp/salty.XXXXXX)"

    lookup "$user" > "$salty_json"

    endpoint="$(jq -r '.endpoint' < "$salty_json")"
    topic="$(jq -r '.topic' < "$salty_json")"
    key="$(jq -r '.key' < "$salty_json")"

    rm "$salty_json"

    message="[$(date +%FT%TZ)] <$(get_user)> $message"

    echo "$message" \
        | salty -i "$SALTY_IDENTITY" -r "$key" \
        | msgbus -u "$endpoint" pub "$topic"
}

make_user () {
    mkdir -p "$HOME/.config/salty"

    if [ $# -lt 1 ]; then
        user=$USER
    else
        user=$1
    fi

    identity_file="$HOME/.config/salty/$user.key"

    if [ -f "$identity_file" ]; then
        printf "user key exists!"
        exit 1
    fi

    # Check for msgbus env.. probably can make it fallback to looking for a config file?
    if [ -z "$MSGBUS_URI" ]; then
        printf "missing MSGBUS_URI in environment"
        exit 1
    fi


    salty-keygen -o "$identity_file"
    echo "# user: $user" >> "$identity_file"

    pubkey=$(grep key: "$identity_file" | awk '{print $4}')

    cat <<- EOF
Create this file in your webserver well-known folder. https://hostname.tld/.well-known/salty/$user.json

{
  "endpoint": "$MSGBUS_URI",
  "topic": "$user",
  "key": "$pubkey"
}

EOF
}

# check if streaming
if [ ! -t 1 ]; then
    stream
    exit 0
fi

# Show Help
if [ $# -lt 1 ]; then
    printf "Commands: send read lookup"
    exit 0
fi


CMD=$1
shift

case $CMD in
    send)
        sendmsg "$@"
    ;;
    read)
        readmsgs "$@"
    ;;
    lookup)
        lookup "$@"
    ;;
    make-user)
        make_user "$@"
    ;;
esac
;-) I seem to remember there being g a script that checks for 1.17. Maybe that is only on make preflight
@prologic I have seen single use keys that are signed by a central PKI .. Keybase has one that uses a chatbot to generate the keys on the fly.

It just comes down to your threat model :)
https://book.keybase.io/docs/chat/crypto
@prologic for shame! lol me too.
I would HIGHLY recommend reading up on the keybase architecture. They designed device key system for real time chat that is e2e secure. https://book.keybase.io/security

A property of ec keys is deriving new keys that can be determined to be "on curve." bitcoin has some BIPs that derive single use keys for every transaction connected to a wallet. And be derived as either public or private chains. https://qvault.io/security/bip-32-watch-only-wallets/
@prologic yarn builds in 1.18!
@prologic hmm so each individual feed on your pod sub's my feed? Wouldn't that flood your server for each post?
Okk
@prologic wat
One down! More to go.

> BREAKING: Russian billionaire Alisher Usmanov's super yacht, one of the biggest in the world, seized in Germany - Forbes
>

https://www.forbes.com/sites/giacomotognini/2022/03/02/germans-seize-russian-billionaire-alisher-usmanovs-mega-yacht/?sh=8b18f5052ddd
I prefer ::1
Tricky #Wordle 240 5/6*

⬛⬛⬛⬛⬛
🟩⬛⬛⬛⬛
🟩⬛🟨🟨⬛
🟩⬛⬛🟩🟩
🟩🟩🟩🟩🟩
Tricky #Wordle 240 5/6*

⬛⬛⬛⬛⬛
🟩⬛⬛⬛⬛
🟩⬛🟨🟨⬛
🟩⬛⬛🟩🟩
🟩🟩🟩🟩🟩
#Wordle 238 4/6*

⬛⬛⬛⬛⬛
⬛⬛🟨🟨⬛
⬛🟨🟩⬛🟨
🟩🟩🟩🟩🟩
#Wordle 238 4/6*

⬛⬛⬛⬛⬛
⬛⬛🟨🟨⬛
⬛🟨🟩⬛🟨
🟩🟩🟩🟩🟩
I think google voice has been winding that down.
#Wordle 237 3/6*

⬛⬛🟨⬛⬛
🟩⬛⬛🟩🟩
🟩🟩🟩🟩🟩
#Wordle 237 3/6*

⬛⬛🟨⬛⬛
🟩⬛⬛🟩🟩
🟩🟩🟩🟩🟩
i agree that lextwt is probably mature enough to have its own lib
yep!
Look at you all using naked links!
Try https://twtxt.net!
#Wordle 235 4/6*

⬛🟨🟨⬛⬛
🟨🟨⬛⬛⬛
⬛⬛🟨🟨🟩
🟩🟩🟩🟩🟩
#Wordle 235 4/6*

⬛🟨🟨⬛⬛
🟨🟨⬛⬛⬛
⬛⬛🟨🟨🟩
🟩🟩🟩🟩🟩
@david
#Wordle 234 3/6*

🟨🟨⬛🟨🟨
🟨🟨🟩⬛🟨
🟩🟩🟩🟩🟩
#Wordle 234 3/6*

🟨🟨⬛🟨🟨
🟨🟨🟩⬛🟨
🟩🟩🟩🟩🟩
@screem we have had to really shorten our process. I think long interviews were scaring off talent.
@screem yah I finally saw all of Dave's twts and figured he had explained Gog's/gitea better.
I call FUaaS
This led me on quite the rabbit hole ending around this site with quite a few pages of different components of the language. https://www.bible.ca/ark/chinese/bible-evidences-chinese-language-characters-words-history-genesis.htm
Its weird to see a tech company be bought by an investment company. Like what is the motivation other than to milk it for investor profit?
Pretty sweet


Wordle 220 4/6*

⬛🟨🟨⬛⬛
⬛🟨🟨⬛⬛
⬛🟩⬛🟩🟩
🟩🟩🟩🟩🟩
@eldersnake yep. And when its sat to sat connections are online it will have better cross planet latency than under sea cable. FWIW
Latency to the sat and back to a uplink station is actually ~45ms because the orbit is so much closer to the ground than say a Hughesnet.~
@prologic they are everywhere.
Yeah the timer is because everyone gets the same word each day. You get one word with 6 trys and compare with friends on how you came to the solution.
I mean you don't even have to do the game to make a fake emoji result. But its a fun little challenge for brain food.
This is like my 5rh day at it. I suck at words and spelling. So this is good practice.
Wow. I'm paying about 100 USD for my cable internet. Hard to estimate since its part of a tvd bundle. But it is 1.2Gbit down and 40Mbit up. And speed tests at that on the regular. The new house will have FTTH gigabit for 80ish.

Do they have Starlink beta down there yet?
Oof.. No hints in the first guess.


Wordle 219 4/6*

⬛⬛⬛⬛⬛
🟨🟨⬛⬛⬛
⬛🟨🟩⬛⬛
🟩🟩🟩🟩🟩
@prologic I dont get it. What am I looking at? The domain 8s missing for me
I always end up on the 4th try


Wordle 217 4/6

⬛🟩🟩⬛⬛
⬛🟩🟩🟨⬛
⬛🟩🟩⬛🟩
🟩🟩🟩🟩🟩
huh so that site doesnt give you the share emoji like wordle.at?
oh my bad.. the official site has a german version..
@lyse this might be of help https://wordle.at/
its like a mix of hangman and mastermind. You try to guess the word. Yellow means the target word has the letter but its in the wrong location. Green means its in the right location.
Wordle 216 4/6

⬛⬛⬛⬛🟨
🟩🟩⬛⬛⬛
🟩🟩🟩🟩⬛
🟩🟩🟩🟩🟩
Wordle 215 4/6

⬛⬛⬛⬛🟨
⬛⬛⬛⬛⬛
🟩⬛🟨⬛🟨
🟩🟩🟩🟩🟩
Not sure really? i see your Joker image fine on my end.
What if i told you for a browser it doesn't matter what the extension is.. it will use the file magic mime value instead.
@fastidious 🕑 Hi, the current time is about a quarter past two in the afternoon 🌅.
@fastidious I am not Amish.. i am Xuu!
inflation benefits the debtor at the expense of the creditor. The real danger is deflation.
@fastidious +1 ...Now just a way to come up with the $20 per twt to store the data.
ftp://test.com
That's better.. Though the cache will need to be perged in affected nodes.
@prologic Well.. well. well.
Hey. I my own local forward tool. https://github.com/JonLundy/sshfwd it uses ssh port forwards.
@prologic what is this?
I have uBlockOrigin on desktop and https://vancedapp.com/ on android. I never see ads on YouTube.

On SmartTV however this would be a nice addition.
I believe the selling point is to "mobile optimize" the page and send it to the browser faster than over mobile network direct.. But yes you are giving them the keys to your kingdom.

I remember similar things back in dialup days where your ISP would proxy things to you and supercompress the images.
I use VScode. Others seemto like JetBrains GoLand.
@fastidious the things Gemini has going for it are mutual TLS and lack of JavaScript. Which makes for a secure albeit boring experience (much like gopher). The fake markdown is a bit of a drag.

A render mode for Gemini probably wouldnt be too hard. There are markdown to Gemini libs out there.

With Web3 the whole trust a 3rd party browser ext + high fees + env impact for compute and storage are serious no gos for me.. I have heard one too many horror stories about clicking the wrong link and some script draining your metamask wallet.
Web3 is a fraud
Haha that guy comes up every time BTC peaks a bit higher. He is never gonna find it.
@prologic why were they even working? Did they think a big warehouse full of shelves of dangers would be safe?
I happy to be reaffirmed that Java is hopelessly over engineered.
@prologic former CEO of Twitter and countless ETH/NFT scammers
The complexity is a feature. It means standards can be replaced with products that let providers get their cut. It means putting data into the slowest most expensive database in cost and enviromnmental impact.
Web3 is a scam. Case in point. The complexity of systems increasing the points of failure. From this article.



vs.

So the evolution of my nick is as follows. I had a bicycle that had the word Zephyr written on it. Which means a western wind. That is related to the Greek god Zephyrus.

I liked words where X make a Z sound. And also had a bit of dyslexia so my firs IRC nick was Xypher swapping the y and e.. I would also use the forms Xypherius or just Xypheri.

Because its close hemming to Cypher I found the nick would get used by others.. Though that is not my origin.

Later I would sign websites I created as The X-Urban Underground (where X was short for Xypher) and that evolved to xuu. Pronounced like zoo.
@lyse ah and here I am pronouncing it in my head like an abbreviated version of Lysine.
DS9 is best Star Trek. And that last second half of the last season where they go all out. *chef kiss*
@fastidious @darch y'all got a passcode for that zoom link?
@thecanine been there a few times! Thank goodness for mosh for when trying to debug from spotty GSM connection and having ssh drop out every few minutes.
@thecanine thoughts and prayers
Not sure what is going on with these?

Love the new icons on the latest update!
If only there was a way to forward feeds for continuity.
@fastidious tbh I wish it were the nick.txt

Like txt.sour.is/xuu.txt
@prologic you get your infra all fixed up?
@lyse What the heck? no emoji? do you even Unicode!
@fastidious Yes. there is a --flag for it. i have mine set for some crazy long time.
I am just posting here so I don't get fined.
@lyse So.. in the great wisdom of markdown parser.. it only provides the Title and deletes the alt. :D i guess i could write out the alt and title as the same value
@lyse https://arrakis.netbros.com/conv/pbd43lq
@lyse there was an old tool for encrypted volumes that you could use random files as the unlock keys. And you could havemultiple hidden volumes that would unlock depending on the files supplied
No on gitlab. If its self hosted gitea is best in class.

I can see hosting a mirror on github if only for the redundancy/visibility. Some projects will host but then direct contributions on their self host. Like Go does.

I would suggest using a vanity domain that can redirect tools like go get to hosting of choice. And not require rewriting all the packages any time it gets moved.
@prologic

> JavaScript : web apps

I understand the hate for JavaScript. But what option is there for writing web enabled applications for desktop / mobile?