You can now click on a nick in the desktop client to open their twtxt file in browser.
Today I’ve been working on something that I’ve really missed, and that is clickable links in the desktop client, finally figured out how they work. So now you can click on them and it opens the browser. I need to clean it up before I commit it.
I added the Yarn Desktop Client and Goovy Twtxt to the landing page for Yarn.social
@prologic@twtxt.net Sure, I’ll do that!
Thank you so much, I’ll start working on getting it into the client tonight.
@prologic@twtxt.net I will stick around, after thinking about it. Im sure support for both will come. Maybe Ill check if I can make some support in snac2 for yarn, that would be a fun project. I also want to work some more on the yarn desktop client, I miss working on it, polish it and make it more feature complete, and then also make one for snac2/activitypub (or make it into a general client that supports both at the same time).
compiled and ran the desktop client on riscv tonight. my mangopi only has 512mb ram, but it was enough to compile and run it :)
@prologic@twtxt.net Thanks :) Looking forward to get that feature in, since I like to share images that I take, will be a nice feature to have in the client as well. :)
I need to do a big rewrite on how the yarn desktop client handles the status widgets, this is because I want links and such, and to do that I have to rewrite the status message code, it takes a bit if time to do it, but I kinda know what to do - I just need to dive in and get it done. Been thinking about it for a while, I think it’s time to get started on it. Also makes the code much cleaner then what it is now.
@apex@twtxt.net - source is here
https://github.com/stig-atle/YarnDesktopClient
Some more info and screenshot:
https://stigatle.no/posts/2023-07-03-yarn-desktop-client/
Keep in mind it’s early still, but a lot of things works and I use it all the time my self..
Just compiled the Yarn desktop client on OpenSuse, was no issues getting it to run there, I love how portable it is. I initially wanted to run OpenBSD on this laptop, but it would not detect wifi, which is a dealbreaker for me, so I installed OpenSuse tumbleweed instead, and will run OpenBSD in a VM and try from there instead.
I had issues with the current activitypub implementation here on yarn (people could not follow me properly) and I cannot see their posts and stuff like that, so I decided to host activitypub separate from here.
So I will turn it off here - and use this site has as before - but without activitypub turned on, and then do all my activitypub stuff over on that other service.
I can be added through: @stigatle@activitypub.stigatle.no
This does not affect the development of the desktop client, I will still work on that, I’m here to stay :) I just need a way to follow the others properly on the other services..
I did not want to join mastodon, and I did not want something complex to host, so I decided to set up Snac2 - https://codeberg.org/grunfink/snac2 . It’s super lightweight, easy to set up, and worked out of the box for what I was looking for.
This whole twitter thing got me motivated to code on the yarn desktop client.
Currently working on adding support for links in the post, so that you can open and view the links that are in the statuses.
wanted to use my oculus to do some flightsimming on Friday, but now Meta forces you over to facebook. super annoying message that constantly pops up in the desktop client, but then after 10 minutes of flying they show the same message in fullscreen inside the VR glasses. so fuck them. I will try and get it to work on linux instead one day soon when I have time.
Hehe, as you all might have noticed - I test OS’es often. NixOS was too much of a pain to work efficiently in (the way I wanted), so hopped over to Fedora now. Got all my stuff working there now, as well as the desktop client. I really like how portable the code is, and how easy it is to compile on different os’es. Installed fedora with LXQT, I really like that desktop, I do not like gnome at all - I really dislike the way gnome works. LXQT is just what I need.
I tested the yarn desktop client on wsl2 on windows 11, compiled and ran just fine there. Nice to have linux applications with gui on windows.
I need to add multithreading to the desktop client, I have not done that before in c++ - so that’ll be fun to figure out. I need it for the fetching of the timeline so that it happens in a separate thread. That way the GUI does not freeze while fetching the timeline. Also need to add a status bar that can show what the application is working on.
no, some client on fdroid
Here is a screenshot showing the client running on NixOS.
Heh, I do not regret it anymore, I was able to create a flake.nix file that builds the desktop client on NixOS.
But I now found a bug with keyring access that I need to fix. but the client compiles and starts.
It does not open the keyring - so it hangs and waits and you need to kill it. On my previous machine the keyring got opened at login by another application.
So, I kinda regret installing NixOS, I had forgotten why I did not use it for c++ stuff last time. But I learned about ‘flakes’ so Im checking into that now to see if I can use that to my advantage to make it easier. So I’ll give it some more time to see if I can learn what I need to build yarn desktop client on it.
I want to try NixOS again, and then get the yarn desktop client built on that, and then see if I can get the client into their repo. That would be fun to do. If I have time tonight I’ll start on that.
Decided to write a bit about the desktop client on my website..
Feel free to read.
Worked a bit on the desktop client tonight, now I store username/pass/server url, but it’s insecure at the moment. I need to find a way to store it more securely.
I need to add ‘thread view’ in the Yarn desktop client, I find my self really missing that when I use it. It will make it much easier to follow threads and such.
Working on showing attached images in the desktop client, it worked on first try.
Now I need to fix the scale and alignment - but cool that it works already!
@funbreaker@twtxt.net I tested now against twtxt with a account I created -it segfaulted if you had a / at the end of the server url.. My bad.. works if you remove the slash. I will fix it in the client so that it removes the slash if it’s in the server url.
I’m not super a fan of using json. I feel we could still use text as the medium. Maybe a modified version to fix any weakness.
What if instead of signing each twt individually we generated a merkle tree using the twt hashes? Then a signature of the root hash. This would ensure the full stream of twts are intact with a minimal overhead. With the added bonus of helping clients identify missing twts when syncing/gossiping.
Have two endpoints. One as the webfinger to link profile details and avatar like you posted. And the signature for the merkleroot twt. And the other a pageable stream of twts. Or individual twts/merkle branch to incrementally access twt feeds.
💡 Quick ‘n Dirty prototype Yarn.social protocol/spec:
If we were to decide to write a new spec/protocol, what would it look like?
Here’s my rough draft (back of paper napkin idea):
- Feeds are JSON file(s) fetchable by standard HTTP clients over TLS
- WebFinger is used at the root of a user’s domain (or multi-user) lookup. e.g:
prologic@mills.io
->https://yarn.mills.io/~prologic.json
- Feeds contain similar metadata that we’re familiar with: Nick, Avatar, Description, etc
- Feed items are signed with a ED25519 private key. That is all “posts” are cryptographically signed.
- Feed items continue to use content-addressing, but use the full Blake2b Base64 encoded hash.
- Edited feed items produce an “Edited” item so that clients can easily follow Edits.
- Deleted feed items produced a “Deleted” item so that clients can easily delete cached items.
The code for the desktop client is now public here: https://github.com/stig-atle/YarnDesktopClient , I will create tickets for the known things I need to fix and such later today.
@prologic@twtxt.net By the way - can I call my application ‘Yarn desktop client’? Is that OK with you? Or do you want it to have another name - but then have ‘a desktop client for yarn’ as information in readme etc?
I will release the sourcecode for the desktop client tonight. I will put it on github (sorry to anyone who prefer other places), but the reason is that I do not want my own git to be open for public. So I’ll put it on github where I have all my other public projects. I have to write the readme, then add some info on the login page (link to source etc), then it’s ready to release with the current features. I then hope others will give it a try and use it if they want :) I also have many other features I need to implement, but all the main features that makes it usable has been implemented, so I’m very pleased with it (And I use it all the time now).
Got up before 7 this morning, now it’s 14,5 hours later - and I finally got to sit down for the first time today. Been a busy day, but a good one. Now it’s time to relax a bit (code on the desktop client) and then relax for a bit. Tomorrow the weather is going to suck, but I’ll still go for the usual weekend hikes with the dog, trying to plan a new place to walk tomorrow.
That reminds me about something, I want to test if I can compile my desktop client on my mangopi riscv board with debian. That would be cool to run on it.
@movq@www.uninformativ.de I love ‘exotic’ computers, especially riscv. But one of the most prized computers I have is the Lemote Yeeloong, Loongson mipsel laptop - http://web.archive.org/web/20151220055337/http://www.lemote.com:80/en/products/Notebook/2010/0310/112.html , very cool machine, I cannot part with that one, gonna put in in my coffin when I die. Got a hold of it about 10 years ago, cost a lot, but it was worth it. I run openbsd on it, and have to compile everything on it. took over 2 weeks to compile sylpheed email client on it LOL.
@lyse@lyse.isobeef.org We use gitlab daily at work. but for my own projects I use gogs. I have some scripts that I used for a gnusocial client that I maintained (before leaving gnusocial). I’ll see if I can adapt that and make deb files for the yarn client - I mostly use debian \ Trisquel my self, so I also like .deb as well.
The GTK gui client is coming along nicely.
Added avatar support, and reply button.
It’s pretty obvious that the GUI does not scale properly yet, but I’ll worry about that once the last feature is added. Now I’m only missing the ‘post status’ gui, I need to think a bit about how I want that implemented.
Anyways - here’s the latest screenshot..
@funbreaker@yn.vern.cc Hi! I have attached the current screenshot, as you see it’s not done yet, I need to add some things, but a lot of work is already done.
I will fix the remaining things and try to make it usable enough this week so that I can upload the source.
Need to add the remaining reply button, image loading and width of the text etc first.
I had that in the FLTK client, so I just need to add it to this new GTK gui.
Here is what I had with FLTK
https://yarn.stigatle.no/twt/4nuoc7q
I did not have time to work on those things today, ran out of time. But I’ll resume tomorrow.
Greetz from Ukraine / Bopher-NG client in action!
Turns out the problem I had was also there when I build rapidjson from source, but if I moved the include to earlier (rapidjson in my project) - the problem went away, so I suspect it’s the same as in this issue going on.
The cool thing is that the client now works fine on linux without changing anything else then the include order!
So now I’ll do all development there - instead of on windows.
Weekend is here :)
I want to create a frontpage for my website - https://stigatle.no , fix cmake script for the desktop client and compile it on debian. Other then that I’ll walk the dog as usual and spend quality time with my family. Going to be a great one :)
@movq@www.uninformativ.de Correct! It’ll be a generic yarn client. :)
I will try and write a small cli example project in rust, that will let you post a message on yarn through a server url. Once I have that - I will then try and write a client with GUI and all that. I have not used rust much - but I really want to learn it more. I usually stick with c++. Not sure how much time it’ll take to get started, but I’ll give it a try.
do anyone know anything about wireguard? I have a VPS, which runs nginx. If I then want tjat to host something from my house, do I then set up vps as wiregiard server, connect from my house to it - and then serve the wireguard client? or do it the other way around? I think I have to look into it this weekend. would be a nice way to test out things.
@mckinley@twtxt.net i use pass along with the android and browser-pass clients. it is very good and keeping in sync is pretty simple.
The most secure way to access this site is to torify a gopher client and go to the onion address.
@kdx@kdx.re: I suggest you to try twtwt client, it’s also written in C: https://github.com/win0err/twtwt
projects: built raven, a small twtxt client in go
And working on my TUI client again 👍
@prologic@twtxt.net I guess that refresh
field could be easily replaced with Expires
HTTP header (I realize that users on neocities.org cannot control this header, for example). And clients should also respect headers like Last-Modified
/If-Modified-Since
(304), you’re right about that. P.S. twtwt doens’t have a caching mechanism for now, but I plan to implement it in generic way using HTTP headers.
@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
I switched from twtxt client to twtwt (https://github.com/win0err/twtwt). It’s a pre-alpha version now, but it works pretty well and so much faster than the official twtxt client by @buckket@buckket.org. Feel free to check it out :-)
Welcome back, @quark@ferengi.one! Your web server doesn’t send back a Last-Modified
header for your feed, so the official twtxt client complains not to cache it. I just fixed that, so that tt shows your feed (of course no progress has been made in the meantime). And the Date
header of your server seems to be quite funny, too. ;-)
(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
}
hm, testing latest mobile client, seems like replies does not work. hmm.
Just testing my new fancy twtwt client written in C
@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 realized my twtxt client isn’t validating what it pulls once it gets a valid response when a domain started returning js-heavy parking pages for every URL. Oops. Weekend project, I guess. 🤦🏻
O client do twtxt para o Emacs precisa de um upgrade.
@prologic moving around servers, managed to break my twtxt client so using literally the first one I could find
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.
Wallops 1.1 Released
A large update to my Wallops IRC client is available: ⌘ Read more
@benk@kwiecien.us I haven’t actually looked at the original twtxt client, which means the following is ill-conceived speculation, but I believe that it only fetched feeds when you “refreshed”, with a minimum time between feed fetches. Sure, you’ll fetch feed unnecessarily now and then, but not nearly as often as polling every 5 minutes ;)
Wallops 1.0 Released
As teased on Twitter, the first release of my Wallops IRC client is now available: ⌘ Read more
@benk@kwiecien.us I meant literally a few minutes 😄 @prologic@twtxt.net told me he’d just implemented it. Btw, which twtxt client are you using now, Ben?
GoCN 每日新闻(2021-12-22)
GoCN 每日新闻(2021-12-22)- 使用 Go 和 SQLite 构建生产应用程序
- 使用 context.Context 模拟 API 客户端https://incident.io/blog/golang-client-mocks
- 一种可嵌入的 Go 脚本语言,实现了逻辑编程语言 Prologhttps://github.com/ichiban/prolog
- SSA:终于知道编译器偷摸做了哪些事[https://mp.weixin.qq.com/s/nOhMsMeP1pUFEXKAMUzbWg](https://mp.weixin.qq.com/ … ⌘ Read more
@stackeffect@twtxt.stackeffect.de
I am seeing this characters on your twts: )?â\200¨â\200¨. Which client are you using?
@stigatle@twtxt.net
A twtxt client would be nice! Or a very simple cgi script to print twts to web nicely—not a second Yarn, just something to show twts in a pretty form on the web.
@eldersnake@yarn.andrewjvpowell.com
RSS links are archaic. Clients discover them if properly linked, they do not need to be human visible.
hurrah! xrxs client works~ there is a new blog post about all things xrxs
I am noticing that Yarn doesn’t treat “outside” (that is, twts coming from a client other than Yarn) twts hashes right. Two examples:
There are many more, but those two will give you the gist. Yarn links the hash to the poster’s twtxt.txt, so conversation matching will not work.
@lyse@lyse.isobeef.org Unless you are stripping stuff on your twts, there is no much to implement. Things will be bold , italics , underlined , and so on, on a client that can render them. Since jenny uses Mutt, I can use my own regex in it to color them as I like. That’s pretty much it.
GitHub security update: revoking weakly-generated SSH keys
On September 28, 2021, we received notice from the developer Axosoft regarding a vulnerability in a dependency of their popular git GUI client - GitKraken. An underlying issue with a dependency, called `keypair`, resulted in the GitKraken client generating weak SSH keys. ⌘ Read more
@benk@kwiecien.us I’ve logged in to Monad now (iOS XMPP client) but I’ve gotta be honest: I don’t know if I’ve created a user in the app or logged in to tilde.team 🤔 Do you happen to know how I join a group? And which groups do you recommend?
Exploring spartan (spartan.mozz.us)! Also trying to make simple client on netcat
I and @r1k@r1k.tilde.institute developing new client for twtxt: https://tildegit.org/g1n/twtxt-c
Fixed another bug in my finger client: rfc1288 says lines have to end with crlf, but I was just sending lf.
Indeed! I think the first “network protocol client” I ever wrote was something that just did the PING/PONG part and passed everything else raw.
Looking at raw IRC traffic streams to debug a client issue and it’s 1997 again.
Sure. I think search, if it’s going to exist, should be the client’s responsibility. But I also value the readability of the raw twtxt file a lot more than y’all do.
I want read-only iOS client that just does the simplest model: pull a list of feeds, make a timeline.
@xjix@xj-ix.luxe Saw your oldish note about wanting an offline/async twtxt workflow. Do you have something that works for you? My (very young!) client was designed with that in mind.
I agree clients should present things better (part of why I’m writing one!). But that should be additive. There’s a reason we’re not passing json around.
@prologic@twtxt.net Exactly, but that reduces the argument for URLs in the post. The client should figure out how to search based on the hashtag.
My silly Plan 9 rc twtxt client now has a web page: http://txtpunk.com/tw/index.html
@prologic@twtxt.netYes, I think tags should just be #foo, and let the client figure out searching if it cares.
@movq@www.uninformativ.de No argument that threading is an improvement. But I think (#hash) does that, and I think figuring out how to search should mostly be up to the client.
Hah… my silly twtxt client now has “stories” mode.☺
@prologic@twtxt.net deedum for android.
Kristall for OS X
Elaho for iOS
though I can only vouch for the first two.
what clients support this?
I have a working model for the reader portion of what I want this twtxt client to do.
@ “that’s it. I’m sticking to this txtnish client.” Solid choice.
that’s it. I’m sticking to this txtnish client.
that’s it. I’m finding another twtxt client.
Learn about ghapi, a new third-party Python client for the GitHub API ⌘ https://github.blog/2020-12-18-learn-about-ghapi-a-new-third-party-python-client-for-the-github-api/
Can we not have clients sign their own public keys before listing them on their Pod’s account?
Yeah.. we probably could. when they setup an account they create a master key that signs any subsequent keys. or chain of signatures like keybase does.
Scuttlebutt is an interesting space. I’m using the Patchwork client and so far it works great!