@prologic@twtxt.net: I understand the benefits of using hashes, itâs much easier to implement client applications (at the expense of ease of use without the proper client). I must say that I like the way the metadata extension is done. Simple and elegant! Itâs hard to design simple things!
@prologic@twtxt.net On the one hand, twtxt has become more popular thanks to Yarn.social. On the other hand, subject and hashtag extensions took away the simplicity of the protocol. For example, it is impossible to understand which conversation (#base32hash) a tweet refers to or to reply to a tweet without going to a yarn.social pod. Compare with re: in this tweet which can be written without using any client at all
one that i think is pretty interesting is building up dependent constraints. see here.. it accepts a type but requires the use of a pointer to type.
https://github.com/sour-is/ev/blob/main/pkg/es/es.go#L315-L325
Tutorial: Getting started with generics - The Go Programming Language â Okay @xuu@txt.sour.is I quite like Goâs generics now đ€Ł After going through this myself I like the semantics and the syntax. Iâm glad they did a lot of work on this to keep it simple to both understand and use (just like the rest of Go) đ #GoLang #Generics
Anyone uses the putr command? (to access pdp11 disk images)
Learning how to use ImageMagick for something else than just for resizing of pictures.
$name$
and then dispatch the hashing or checking to its specific format.
I have submitted this to be used as the hash tooling for Yarn. See it as a good example on using this in a production environment!
Logged in using new argon2i password hash!
I made a thing. Its a multi password type checker. Using the PHC string format we can identify a password hashing format from the prefix $name$
and then dispatch the hashing or checking to its specific format.
@eaplmx@twtxt.net i used internet when it cost 13c per minute. my parents would get so mad if i went over the monthly base minutes CompuServe gave us.
@prologic@twtxt.net duud use an ad block on youtube.
ahh this is useful https://go.dev/doc/modules/managing-dependencies. the go culture doesnât typically have large dependency graphs like Ruby or JS.
@lyse@lyse.isobeef.org @prologic@twtxt.net yeah that was how i did it too. I think ill start using the debug version in new stuff since its been added. My comment was around assigning the result of an anonymous function to a a variable.
Tell me you write go like javascript without telling me you write go like javascript:
import "runtime/debug"
var Commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {
for _, setting := range info.Settings {
if setting.Key == "vcs.revision" {
return setting.Value
}
}
}
return ""
}()
@mckinley@twtxt.net Thank you! I didnât even know about signing and encrypting XML documents. Right, RSS is a little bit messy.
Unfortunately, the autodiscovery document in one of your linked resources does not exist anymore. What annoys me in Atom is the distinction between <id>
and <link>
. I always want my URL also to be my ID, so I have to duplicate that â unnecessarily in my opinion.
Also, never found a good explanation why I should add <link rel="self" ⊠/>
to my feeds. I just do, but I donât understand why. The W3C Feed Validation Service says:
[âŠ] This value is important in a number of subscription scenarios where often times the feed aggregator only has access to the content of the feed and not the location from which the feed was fetched.
This just sounds like a very questionable bandaid to bad software architecture. Why would the feed parser need access to the feed URL at this stage? And if so, why not just pass down the input source? Just doesnât make sense to me.
Also, I just noticed that I reference the http://purl.org/rss/1.0/modules/syndication/
namespace, but donât use it in most of my feeds. Gotta fix that. Must have copied that from my yfav feed without paying attention what Iâm doing.
Your article made me reread the Atom spec and I found out, that I can omit the <author>
in the <entry>
when I specify a global <author>
at <feed>
level. Awesome! Will do that as well and thus reduce the feed size.
it uses the queries you define for add/del/set/keys. which corrispond to something like INSERT INTO <table> (key, value) VALUES ($key, $value)
, DELETE ...
, or UPDATE ...
the commands are issued by using the maddycli but not the running maddy daemon.
see https://maddy.email/reference/table/sql_query/
the best way to locate in source is anything that implements the MutableTable interface⊠https://github.com/foxcpp/maddy/blob/master/framework/module/table.go#L38
I was inclined to let this go so as not to stir anything up, but after some additional thought Iâve decided to call it out. This twt:
is exactly the kind of ad hominem garbage I came to expect from Twitterâą, and Iâm disappointed to see it replicated here. Rummaging through someoneâs background trying to find a âgotchaâ argument to take credibility away from what a person is saying, instead of engaging the ideas directly, is what trolls and bad faith actors do. Thatâs what the twt above does (falsely, I might addâwhatâs being claimed is untrue).
If you take issue with something Iâve said, you can mute me, unfollow me, ignore me, use TamperMonkey to turn all my twts into gibberish, engage the ideas directly, etc etc etc. There are plenty of options to make what I said go away. Reading through my links, reading about my organizationâs CEOâs background, and trying to use that against me somehow (after misinterpreting it no less)? Besides being unacceptable in a rational discussion, and besides being completely ineffective in stopping me from expressing whatever it is you didnât like, itâs creepy. Donât do that.
Very cool. I am digging the multipurpose use for this kind of parser.
@movq@www.uninformativ.de, well, yes, that has always been the case. Not just on jenny, but on Yarn. I canât follow everything, and everyone. To see whether is a reply, a simple h
on mutt shows the headers, and there you have it. That is not too convoluted, is it? I mean, if you really want to knowâbut why?âit is a simple key press. If I donât see a context on something as obvious as the example you used, it is simply a reply to someone I donât follow, and pretty much ignore. End of story. đ
@movq@www.uninformativ.de, any plans still to clean up the hash from the twtxtâs body? Maybe a Festivus gift? You know, âfor the rest of usâ. :-D
đŁ NEW: Announcing the new and improved Yarns search engine and crawler! search.twtxt.net â Example search for âHello Worldâ Enjoy! đ€ â @darch@neotxt.dk When you have this, this is what we need to work on in terms of improving the UI/UX. As a first step you should probably try to apply the same SimpleCSS to this codebase and go from there. â In the end (didnât happen yet, time/effort) most of the code here in yarns
will get reused directly into yarnd
, except that Iâll use the bluge indexer instead.
@abucci@anthony.buc.ci Do you happen to use Signal btw? đ€ If you do, it would be great if you could join the Yarn.social Signal Group (_at least until we have Group support and better apps for Salty.im đ )
I think Email has been broken on my Pod since some time now since @lyse@lyse.isobeef.org made this commit the default behaviour of the flags/env had changed requiring SMTP_PORT
to be set (used to default toi 25
) ooops đ
@xuu@txt.sour.is proof of stake = people with money get more money. It accelerates the wealth inequality problems that are already plaguing us. Crypto has even worse wealth inequality than fiat currency systems, which is 100% predictable.
-1 for the negative on environment all that electricity uses. Still waiting on proof of stake.
It is also too overrun with Tech Bros scamming people to get rich quick.
It was a fun ride back when I first bought in. But I have since cached out for my lambos and such.
80,000 hours podcast but itâs only Rob Wiblin speaking. Useful for voice synthesis.
@abucci@anthony.buc.ci Its not better than a Cat5e. I have had two versions of the device. The old ones were only 200Mbps i didnât have the MAC issue but its like using an old 10baseT. The newer model can support 1Gbps on each port for a total bandwidth of 2Gbps.. i typically would see 400-500Mbps from my Wifi6 router. I am not sure if it was some type of internal timeout or being confused by switching between different wifi access points and seeing the mac on different sides.
Right now I have my wifi connected directly with a cat6e this gets me just under my providers 1.3G downlink. the only thing faster is plugging in directly.
MoCA is a good option, they have 2.5G models in the same price range as the 1G Powerline models BUT, only if you have the coax in wall already.. which puts you in the same spot if you donât. You are for sure going to have an outlet in every room of the house by code.
I maintain keys for my email addresses.. but like most in this thread i almost never receive encrypted emails.. other than the BTC exchange i use that sends automated mail encrypted.
I use IP over Alternating Current at home. The only issue is the bridges forget device MACs sometimes and I get weird states where I can ping a deviceA and the the internet from deviceB. But deviceA can only ping device B even though they are on the same subnet and default gateway.
Does anyone of you use PGP encrypted mail, or any kind or email encryption? Why? Why not?
@prologic@twtxt.net I think we could use deltachats new decentralising app format for it: https://delta.chat/en/2022-06-14-webxdcintro
đ Hello @burglar@txt.sour.is, welcome to txt.sour.is, a Yarn.social Pod! To get started you may want to check out the podâs Discover feed to find users to follow and interact with. To follow new users, use the âš Follow
button on their profile page or use the Follow form and enter a Twtxt URL. You may also find other feeds of interest via Feeds. Welcome! đ€
(cont.)
Just to give some context on some of the components around the code structure.. I wrote this up around an earlier version of aggregate code. This generic bit simplifies things by removing the need of the Crud functions for each aggregate.
Domain ObjectsA domain object can be used as an aggregate by adding the event.AggregateRoot
struct and finish implementing event.Aggregate. The AggregateRoot implements logic for adding events after they are either Raised by a command or Appended by the eventstore Load or service ApplyFn methods. It also tracks the uncommitted events that are saved using the eventstore Save method.
type User struct {
Identity string ```json:"identity"`
CreatedAt time.Time
event.AggregateRoot
}
// StreamID for the aggregate when stored or loaded from ES.
func (a *User) StreamID() string {
return "user-" + a.Identity
}
// ApplyEvent to the aggregate state.
func (a *User) ApplyEvent(lis ...event.Event) {
for _, e := range lis {
switch e := e.(type) {
case *UserCreated:
a.Identity = e.Identity
a.CreatedAt = e.EventMeta().CreatedDate
/* ... */
}
}
}
Events
Events are applied to the aggregate. They are defined by adding the event.Meta
and implementing the getter/setters for event.Event
type UserCreated struct {
eventMeta event.Meta
Identity string
}
func (c *UserCreated) EventMeta() (m event.Meta) {
if c != nil {
m = c.eventMeta
}
return m
}
func (c *UserCreated) SetEventMeta(m event.Meta) {
if c != nil {
c.eventMeta = m
}
}
Reading Events from EventStore
With a domain object that implements the event.Aggregate
the event store client can load events and apply them using the Load(ctx, agg)
method.
// GetUser populates an user from event store.
func (rw *User) GetUser(ctx context.Context, userID string) (*domain.User, error) {
user := &domain.User{Identity: userID}
err := rw.es.Load(ctx, user)
if err != nil {
if err != nil {
if errors.Is(err, eventstore.ErrStreamNotFound) {
return user, ErrNotFound
}
return user, err
}
return nil, err
}
return user, err
}
OnX Commands
An OnX command will validate the state of the domain object can have the command performed on it. If it can be applied it raises the event using event.Raise() Otherwise it returns an error.
// OnCreate raises an UserCreated event to create the user.
// Note: The handler will check that the user does not already exsist.
func (a *User) OnCreate(identity string) error {
event.Raise(a, &UserCreated{Identity: identity})
return nil
}
// OnScored will attempt to score a task.
// If the task is not in a Created state it will fail.
func (a *Task) OnScored(taskID string, score int64, attributes Attributes) error {
if a.State != TaskStateCreated {
return fmt.Errorf("task expected created, got %s", a.State)
}
event.Raise(a, &TaskScored{TaskID: taskID, Attributes: attributes, Score: score})
return nil
}
Crud Operations for OnX Commands
The following functions in the aggregate service can be used to perform creation and updating of aggregates. The Update function will ensure the aggregate exists, where the Create is intended for non-existent aggregates. These can probably be combined into one function.
// Create is used when the stream does not yet exist.
func (rw *User) Create(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil && !errors.Is(err, ErrNotFound) {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
// Update is used when the stream already exists.
func (rw *User) Update(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
Progress! so i have moved into working on aggregates. Which are a grouping of events that replayed on an object set the current state of the object. I came up with this little bit of generic wonder.
type PA[T any] interface {
event.Aggregate
*T
}
// Create uses fn to create a new aggregate and store in db.
func Create[A any, T PA[A]](ctx context.Context, es *EventStore, streamID string, fn func(context.Context, T) error) (agg T, err error) {
ctx, span := logz.Span(ctx)
defer span.End()
agg = new(A)
agg.SetStreamID(streamID)
if err = es.Load(ctx, agg); err != nil {
return
}
if err = event.NotExists(agg); err != nil {
return
}
if err = fn(ctx, agg); err != nil {
return
}
var i uint64
if i, err = es.Save(ctx, agg); err != nil {
return
}
span.AddEvent(fmt.Sprint("wrote events = ", i))
return
}
This lets me do something like this:
a, err := es.Create(ctx, r.es, streamID, func(ctx context.Context, agg *domain.SaltyUser) error {
return agg.OnUserRegister(nick, key)
})
I can tell the function the type being modified and returned using the function argument that is passed in. pretty cray cray.
With respect to logging.. oh man.. it really depends on the environment you are working in.. development? log everything! and use a jeager open trace for the super gnarly places. So you can see whats going on while building. But, for production? metrics are king. I donât want to sift through thousands of lines but have a measure that can tell me the health of the service.
@prologic@twtxt.net Error handling especially in Go is very tricky I think. Even though the idea is simple, itâs fairly hard to actually implement and use in a meaningful way in my opinion. All this error wrapping or the lack of it and checking whether some specific error occurred is a mess. errors.As(âŠ)
just doesnât feel natural. errors.Is(âŠ)
only just. I mainly avoided it. Yesterday evening I actually researched a bit about that and found this article on errors with Go 1.13. It shed a little bit of light, but I still have a long way to go, I reckon.
We tried several things but havenât found the holy grail. Currently, we have a mix of different styles, but nothing feels really right. And having plenty of different approaches also doesnât help, thatâs right. I agree, error messages often end up getting wrapped way too much with useless information. We havenât found a solution yet. We just noticed that it kind of depends on the exact circumstances, sometimes the caller should add more information, sometimes itâs better if the callee already includes what it was supposed to do.
To experiment and get a feel for yesterdayâs research results I tried myself on the combined log parser and how to signal three different errors. Iâm not happy with it. Any feedback is highly appreciated. The idea is to let the caller check (not implemented yet) whether a specific error occurred. That means I have to define some dedicated errors upfront (ErrInvalidFormat
, ErrInvalidStatusCode
, ErrInvalidSentBytes
) that can be used in the err == ErrInvalidFormat
or probably more correct errors.Is(err, ErrInvalidFormat)
check at the caller.
All three errors define separate error categories and are created using errors.New(âŠ)
. But for the invalid status code and invalid sent bytes cases I want to include more detail, the actual invalid number that is. Since these errors are already predefined, I cannot add this dynamic information to them. So I would need to wrap them Ă la fmt.Errorf("invalid sent bytes '%s': %w", sentBytes, ErrInvalidSentBytes")
. Yet, the ErrInvalidSentBytes
is wrapped and can be asserted later on using errors.Is(err, ErrInvalidSentBytes)
, but the big problem is that the message is repeated. I donât want that!
Having a Python and Java background, exception hierarchies are a well understood concept Iâm trying to use here. While typing this long message it occurs to me that this is probably the issue here. Anyways, I thought, I just create a ParseError
type, that can hold a custom message and some causing error (one of the three ErrInvalid*
above). The custom message is then returned at Error()
and the wrapped cause will be matched in Is(âŠ)
. I then just return a ParseError{fmt.Sprintf("invalid sent bytes '%s'", sentBytes), ErrInvalidSentBytes}
, but that looks super weird.
I probably need to scrap the âparent errorâ ParseError
and make all three âsuberrorsâ three dedicated error types implementing Error() string
methods where I create a useful error messages. Then the caller probably could just errors.Is(err, InvalidSentBytesError{})
. But creating an instance of the InvalidSentBytesError
type only to check for such an error category just does feel wrong to me. However, it might be the way to do this. I donât know. To be tried. Opinions, anyone? Implementing a whole new type is some effort, that I want to avoid.
Alternatively just one ParseError
containing an error kind enumeration for InvalidFormat
and friends could be used. Also seen that pattern before. But that would then require the much more verbose var parseError ParseError; if errors.As(err, &parseError) && parseError.Kind == InvalidSentBytes { ⊠}
or something like that. Far from elegant in my eyes.
I have updated my eventDB to have subscriptions! It now has websockets like msgbus. I have also added a in memory store that can be used along side the disk backed wal.
I did a take home software engineering test for a company recently, unfortunately I was really sick (have finally recovered) at the time đą I was also at the same time interviewing for an SRE position (as well as Software Engineering).
Got the results of my take-home today and whilst there was some good feedback, man the criticisms of my work were harsh. Iâm strictly not allowed to share the work I did for this take-home test, and I really can only agree with the âno unit testsâ piece of the feedback, I could have done better there, but I was time pressured, sick and ran out of steam. I was using a lot of libraires to do the work so in the end found it difficult to actually think about a proper set of âUnit Testsâ. I did write one (in shell) but I guess it wasnât seen?
The other points were on my report and future work. Not detailed enough I guess? Hmmm đ€
Am I really this bad? Does my code suck? đ€ Have I completely lost touch with software engineering? đ€Šââïž
Hi, I am playing with making an event sourcing database. Its super alpha but I thought I would share since others are talking about databases and such.
Itâs super basic. Using tidwall/wal as the disk backing. The first use case I am playing with is an implementation of msgbus. I can post events to it and read them back in reverse order.
I plan to expand it to handle other event sourcing type things like aggregates and projections.
Find it here: sour-is/ev
@prologic@twtxt.net @movq@www.uninformativ.de @lyse@lyse.isobeef.org
from now on, when talking about fractions, i will only use the terms âupper numberâ and âlower numberâ. those both have fewer syllables AND theyâre vastly easier to understand. Thank you for coming to my TED talk.
using subscripts for probability assignments?
Web hosting is being moved to Ouvaton, a French co-op and email not sure yet. Might use them or Nubo a Belgian co-op
Finally found the time to set up my Raspberry Pi to do something useful. It was on my shelf for only three years or so.
Iâm trying to switch from Konversation to irssi. Letâs see how that goes. Any irssiers out there who can recommend specific settings or scripts? I already got myself trackbar.pl
and nickcolor.pl
as super-essentials. Also trying window_switcher.pl
. Somehow my custom binds for Ctrl+1/2/3/etc.
to switch to window 1/2/3/etc. doesnât do anything: { key = "^1"; id = "change_window"; data = "1"; }
(I cannot use the default with Alt
as this is handled by my window manager). Currently, Iâm just cycling with Ctrl+N/P
. Other things to solve in the near future:
- better, more colorful and compact theme (just removed clock from statusbar so far)
- getting bell/urgency hints working on arriving messages
- nicer tabs in status bar, maybe even just channel names and no indexes
- decluster status bar with user and channel modes (I never cared about those in the last decade)
@prologic@twtxt.net: 1. I use classic twtxt client written in Python from console, I like simplicity; 2. Thanks for the feedback about my website! Itâs better viewed with old 800x600 monitors, haha
Seems I forgot how to use my twtxt client
I will probably crash in the afternoon but right now I am going to use my energy to take a walk outside
Hmm, @prologic@twtxt.net / @lyse@lyse.isobeef.org: Should we remove the section âTraditional Human-Readable Topicsâ from the spec? Or mark is as deprecated? I havenât seen this being used in the wild for years. đ€
@chronolink@chrono.tilde.cafe Replies are not part of the original twtxt format. They were added later as an extension by Yarn.social: https://dev.twtxt.net/doc/twtsubjectextension.html (only the section âMachine-Parsable Conversation Groupingâ is used these days)
@prologic@twtxt.net Oh.. reading comprehension is strong today.. you went to US and now back.
We moved to the US. When we got back we just never got new chickens again đą
@movq@www.uninformativ.de I usually only use eggs for baking or fry them for potatoes and spinach. @prologic@twtxt.net Why donât you have them anymore? Did the fox get them all when the door didnât close in time? ]:->
you know that youâve made it when youâre using fermi estimates to debug your rl agent.
âif enough of us listen to prophets of doom, it becomes self-fulfillingâ â Leo Szilard
at least iâm up to a level where iâm reading a comment on an acx post and someone uses âconsciousnessâ and iâm hella out there real quick
âŠâŠâŠâŠâŠTetlock data uses AMERICAN DATE FORMAT IN A DATASET
the words âbrier scoreâ are used inconsistently: sometimes they just refer to the MSE of the probability assigned to the correct outcome, sometimes they refer to the MSE of the sum of the probability assigned to the correct and the incorrect outcome.
itâs funny, conditional on AGI (and perhaps also WBE?) not doing us in, iâm pretty bullish on this century. bio seems much less of a problem, and everything else is basically a-okay, especially with people becoming richer and needing to fight less. most other collapse narratives sound pretty unlikely (though prepping is sitll a good idea! you should have three months of food & water at home)
All this time spent being grumpy about how adding my Now updates directly into the html page is uncomfortable, and it just occurred to me I can chug it into a text file and use cat.
i think eliezer wanted micatwoa to take place in a world that was even more insane than here for us to more clearly see whatâs wrong with our world, and the only way he could come up to accomplish that was to make the story take place in actual hell.
@prologic moving around servers, managed to break my twtxt client so using literally the first one I could find
tried to figure out how to use university springer access to download a textbook, gave up after two minutes and just used libgen. lmao
@mutefall@twtxt.net interesting.. were you working on one of the two universities that used it between 1989 and 1991?
started using esglua, our static site generator | https://compudanzas.net/esglua.html
use known inconsistencies of human preferences as value-learning trip-wires: if the value learning algorithm hasnât learned them yet, itâs operating at the wrong level of abstraction.
@prologic@twtxt.net yeah. For commercial use even. Just need to put an attribution note in the project README
@xuu@txt.sour.is So that means weâre allowed to use it right? đ
@lyse@lyse.isobeef.org Excellent use of old denim, and also excellent use of long-form twt!
Alright, check this out. I just kinda completed todayâs project of converting a jeans into a saw bag. Itâs not fully done, the side seams on the flap need some more hand sewing, thatâs for sure. No, I donât have a sewing machine. Yet?
At first I wanted to put in the saw on the short side, but that would have made for more sewing work and increased material consumption. As a Swabian my genes force me to be very thrifty. Slipping in on the long side had the benefit of using the bottom trouser leg without any modification at all. The leg tapers slightly and gets wider and wider the more up you go. At the bottom itâs not as extreme as at the top.
The bag is made of two layers of cloth for extra durability. The double layers help to hide the inner two metal snap fastener counter parts, so the saw blade doesnât get scratched. Not a big concern, but why not doing it, literally no added efforts were needed. Also I reckon it cuts off the metal on metal clinking sounds.
The only downside I noticed right after I pressed in the receiving ends of the snap fasteners is that the flap overhangs the bag by quite a lot. I fear thatâs not really user-friendly. Oh well. Maybe I will fold it shorter and sew it on. Letâs see. The main purpose is to keep the folding saw closed, it only locks in two open positions.
Two buttons would have done the trick, with three I went a bit overkill. In fact the one in the middle is nearly sufficient. Not quite, but very close. But overkill is a bit my motto. The sides making up the bag are sewed together with like five stitch rows. As said in the introduction, the flap on the hand needs some more love.
Oh, and if I had made it in a vertical orientation I would have had the bonus of adding a belt loop and carrying it right along me. In the horizontal layout thatâs not possible at all. The jeans cloth is too flimsy, the saw will immediately fall out if I open the middle button. Itâs not ridgid enough. Anyways, I call it a success in my books so far. Definitely had some fun.
#!/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
ssh
client, because that's me, no-matter where I am. The only exception to this rule is I usually create a separate key for any "work" / " company" I am a part of.
@prologic@twtxt.net 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 :)
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/
For instance I normally use the same RSA key/pair on all my workstations for my ssh
client, because thatâs me, no-matter where I am. The only exception to this rule is I usually create a separate key for any âworkâ / â companyâ I am a part of.
@prologic@twtxt.net ⊠Australia, or The US when visiting www.om.gay
@prologic@twtxt.net on the cheap, I have 4 web hosting accounts used for various things in the past in places
#makeartnotwar #GLSL #shaders code at https://www.shadertoy.com/view/fs2fRm if you want to use it
when trying to learn a formula using flashcards, prefix the formula with a natural-language explanation. makes it easier to remember.
millenial woman who did a degree in *-studies and uses the word âcommunitiesâ a lot
i hope that after iâve aged, I will approach technology with the mindset of either âhow can i use this to make cool shitâ or âhow can i make this technology saferâ.
Look at you all using naked links!
Try https://twtxt.net!
Wikipedia article on Banach spaces: âMaurice RenĂ© FrĂ©chet was the first to use the term »Banach space« and Banach in turn then coined the term »FrĂ©chet space.«â that is very cute.
Will have to take a look at Gogs. Ideally wanting it to be easy to have the same ease-of-use to setup a web page as Github and Gitea.
Iâve been running some internal usenet groups for a while, now Iâm starting to make more use of them and slap them on the web - https://omg.singles/T7ggI
Cloud Computing and Virtualization Company Citrix To Be Acquired for $16.5B
Citrix, a cloud computing and virtualization company used by companies including Microsoft, Google, and SAP, has revealed plans to be acquired by affiliates of global investment firm Vista Equity Partners, and an affiliate of Elliott Investment Management called Evergreen Coast Capital Corporation. From a report: The all-cash deal i ⊠â Read more
@benk@kwiecien.us I am using jenny (we chatted a bit on IRC earlier today). I have been using it for over five months now, I think. It is truly a joy to use, specially because you can use the power of Mutt/NeoMutt to read your twts.
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.
@prologic@twtxt.net let us take the path of less resistance, that is, less effort, for now. I am going to be a great-grandfather before search ever get implemented locally, least one to search on âall podsâ. In other words, let us donât bite more than we can chew. đč Neep-gren!
@prologic@twtxt.net I fully agree with making it a pod-level setting (forget about user-level, let us not complicate things too much; we all know users know nothing). Should I send a latinum over for this, or will an issue just suffice? Neep-gren!
iOS has had a âShortcutsâ app for a while now which is very useful for scripting things on the device, and at some point grew the ability to run things via ssh, including piping input/output. Itâs how Iâve done twtxt from my phone for a while now. Iâll clean up these two examples and post to the examples Iâve shared. http://a.9srv.net/shortcuts
Netflix Raises Monthly Subscription Prices in US, Canada
Netflix has raised its monthly subscription price by $1 to $2 per month in the United States depending on the plan, the company said on Friday, to help pay for new programming to compete in the crowded streaming TV market. From a report: The standard plan, which allows for two simultaneous streams, now costs $15.49 per month, up from $13.99, in the Unite ⊠â Read more
@lyse@lyse.isobeef.org that is a horrible idea. A mobile device isnât a server. Having a mobile device pull raw twtxt feeds from everywhere on an ongoing bases, will be, at the very least, tolling on the deviceâs battery. Just at you, or even further, I will never use such thing.
@tamer@twtxt.net Weâre not trying to compete with anything⊠If youâve read About Yarn.social â In a nutshell I want to create an open, transparent social platform that respectâs folks privacy and freedoms. It must also be easy to use and down-to-earth where human interactions actually matter. None of this rubbish of manipulating what you see, driving up engagement numbers to serve your advertisers and all that garbage
I think yâall are missing something. I never used ftp as a schema; Iâm saying the âftpâ hostname part with the âhttpâ schema is amusing.
from now on, i will use î” whenever abbreviating the Fast Fourier Transform
trying to justify using tinyscheme, lua, and LIL at the same time.
Hey. I my own local forward tool. https://github.com/JonLundy/sshfwd it uses ssh port forwards.
FOLLOW: @watcher@txt.sour.is from @prologic@twtxt.net using yarnd/0.10.0@4618bd0
Hey @eldersnake@yarn.andrewjvpowell.com I just came across this cool little project recently. Not written by me sadly đ But seems like it would do the trick nonetheless đ€Ł â How are you going with PageKite? Is it still working okay for your Yarn pod powered by the outback of down under? đ LMK if youâd like me to spin this up anad you can be my first tester đ€