💾 Archived View for ix.cyb.red › wiki › pikabu captured on 2024-03-21 at 15:07:17. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-09-28)

➡️ Next capture (2024-06-16)

🚧 View Differences

-=-=-=-=-=-=-

pikabu (gemini social)

a cute gemini socnet with offline capabilities

cute pages like tumblr that's easy to learn. facilitating social applications of gemini shouldn't require new additions to the protocol, but for the sake of interoperability of social gemini clients and servers we'll try to outline a set of conventions for reading and writing to the social gemspace. for the most part, this will consist of document formats and url structure. gemini social pages should not be distinguished from other kinds of gemini documents, though certain special documents will have strict format requirements.

most existing content in gemini space should be considered conformant to this spec. the few extensions proposed here provide basic pki and inter-site commuication methods with basic privacy. this document intentionally does not specify how user content is provided to the network. though, its pretty clear that gemini+social+titan is going to be the most user-friendly option.

capsule archive format

pikabu is a zine-centric social network.

a capsule archive is built on the gemini ebook format gempub. end users and their server host are not expected to provide already-compressed archives, though social servers may generate/cache them to minimize download bandwidth for clients.

a simple script can be used to parse this standard gempub file and download the rest of the gempub archive. minor extensions to the metadata file allow clients and servers to establish coms using the pikabu server protocol.

gemini ebook format

the gist of the spec is sketched below.

directory structure

Gempub files are zip archives that contain a Gempub index file (see "Gempub Index", below), a collection of text/gemini (.gmi) files, any supporting files such as images (see "Images", below), and an optional metadata file containing the title, author and any other optional fields (see "Metadata", below).

// Example with index.gmi in a sub-directory, specified by the index value in metadata.txt

// .gpub contents:
book_title.gpub/
   metadata.txt
   cover.jpg
   book/
      index.gmi
      chapter1.gmi
      chapter2.gmi
      chapter3.gmi
      images/
         illustration.png

// metadata.txt:
title: book title
gpubVersion: 1.0.0
cover: cover.jpg
index: book/index.gmi

metadata file

The metadata.txt file enables Gempub to act as a full e-book format by allowing the author to specify data such as a title, a cover image, copyright information, a book description, and author information.

The metadata.txt file contains key-value pairs separated by line. Values start after the first colon and are trimmed (e.g., author: Olaf Stapledon and author:Olaf Stapledon are equivalent). All values are optional apart from title and gpubVersion. Order does not matter. If no index path is specified there must be an index.gmi in the directory root.

This metadata is intended for readers to use to display a useful catalogue of multiple .gpub files and display covers for individual books. Metadata must never be used to specify flags for content rendering. Content should always be plain Gemtext. Reader applications must ignore custom parameters.

title: my-zine
author: xj9
cover: path/to/cover.jpg
index: path/to/index.gmi
language: nah
version: ???whatmeta?
publishDate: 19785
license: path/to/license.txt
gpubVersion: 1.0.0
pikabuBeaconUrl: gemini://sunshinegardens.org/~xj9/bin/pikabu
pikabuFileInfo: crc.txt

markup

gemtext

feeds

[ ] gemini subscriptions

lots of gemini clients support subscribing to feeds in this format:

# FEED TITLE
DESCRIPTION
## FEED SUBTITLE
=> URL	YYYY-MM-DD - TITLE

gemini feeds and backlinks can be used for pull-based threaded conversations.

server protocol

VERY EXPERIMENTAL

a set of scripts that demo various experimental social extensions. all operations can be done using plain gemini requests.

some gemini servers allow certain routes to be access restricted based on the pubkey of the client. that's about 80% of a consent-based social network. the remaining 20% is follow requests, a UI for accepting them, and a permission-aware feed aggregator.

installing these may vary depending on your gemini server software. in the future, we may define these interfaces in a more general way.

basically, you need two things

the same pikabu command does can be used for both. just download it somewhere convenient that works with your cgi software. here, "/path/to/db" should match the environment variable PIKKABU_DB_PATH in the cgi settings. for multiple instances, try staggering the cron jobs.

15 * * * * /path/to/pikabu cron -d /path/to/db

pikkabu has a few settings, these are controlled with an indental document:

SYSOPS
	lain
		00100010
		01001110
		01000010
		00100010

follow-request

could be combined with an "inbox" feature to provide a simple DM push service.
gemini://$target/pikabu/_follow-request?keyid=$TLS_CLIENT_HASH&uri=$SELF_URL&i=$MESSAGE
#!/usr/local/plan9/bin/rc
path = (/usr/local/plan9/bin)
# opts
capsule_url = 'gemini://sunshinegardens.org/~xj9'
dreamers_db = /srv/gemini/.cache/follow-request.db
# mkdir -p $dreamers_db
# script
if (~ $"TLS_CLIENT_HASH '') { echo 60 id please.
 }
if not {
	dreamer = $"TLS_CLIENT_SUBJECT_CN
	did = $"TLS_CLIENT_HASH
	follow_record_path = $dreamers_db/$"did.gmi
	if (~ $"QUERY_STRING '') { echo 10 helllllo stranger. liiiiike to leave an introducccccction'?'
 }
	if not {
		echo '# follow request from' $dreamer > $follow_record_path
		echo $"QUERY_STRING >> $follow_record_path
		echo 20 text/gemini
		echo '# request recieved!'
		echo iiiiiiiii hoooooooooooope yyyyyyyour note waaaas convincing '^^'
		echo '=>' $capsule_url 'return to capsule'
		echo '=>' $capsule_url/wiki/pikkulog/ pikkulog docs
		echo '## transcript'
		cat $follow_record_path
		echo '=> magnet:?x.bb=1312&xt=urn:sha256:'^$did^'&dn="~gemini/'^$dreamer^'"'
	}
}

prompt/add-device

prompt/rm-device

prompt/add-topic

prompt/rm-topic

sub

docs

#!/usr/bin/env rc
# CHAOTIC SOFTWARE : BEWARE
# This is free and unencumbered software released into the public domain.
# gemini://xj-ix.luxe/chaotic-software/
. ./system/lib/list.rc
. ./system/lib/gemtext.rc
fn parse_urls {
	feed_list = $1
	# parse_urls FEED_LIST
	fn handle_to_file_name {
		url=$1
		handle=$2
		echo ($url `{echo $handle | 9 sed s,/,__,g})
	}
	pair_fold handle_to_file_name `{
		cat $feed_list \
		| 9 grep '^=>' \
		| 9 sed -ne 's,^=> (gemini|gopher)://(.+?) ~(.+)$,\1://\2\n\3,p'
	}
}
fn fetch_feeds {
	feed_list = $1
	cache = $2
	# fetch_feeds FEED_LIST CACHE
	fn cache_capsule {
		url=$1
		handle=$2
		# cache_capsule URL HANDLE
		## store encoded url in record name so we can normalize the canonical feeds
		## when we read them.
		encoded_url = `{echo -n $"url | base64 | tr -d '
' | sed 's, ,,g'}
		feed_record = $"cache/^$"handle^@^$"encoded_url^.gmi
		echo frfr $encoded_url
		echo fetching url:$"url '->' id:$"feed_record >[1=2]
		memex gemget $"url > $"feed_record
	}
	rm $cache/*.gmi
	pair_fold cache_capsule `{parse_urls $feed_list}
	echo 'OK' >[1=2]
}
fn parse_feeds {
	# parse_gemlogs FEED...
	for (feed in $*) { parse_gemlog $feed }
}
default_cache = data/feeds/.cache
default_feed_list = data/bookmarks/feeds.gmi
switch ($1) {
case cron
	shift
	feed_list = $1
	if (~ $"feed_list '') { feed_list = $default_feed_list }
	cache = $2
	if (~ $"cache '') { cache = $default_cache }
	fetch_feeds $feed_list $cache
case cache
	shift
	cache = $1
	if (~ $"cache '') { cache = $default_cache }
	9 ls -l $cache/*.gmi
case ls
	shift
	feed_list = $1
	if (~ $"feed_list '') { feed_list = $default_feed_list }
	parse_urls $feed_list
case feed
	shift
	cache = $1
	if (~ $"cache '') { cache = $default_cache }
	parse_feeds $cache/*.gmi | 9 sort -ur +2 | 9 head -n 69
case view
	shift
	handle = $1
	cache = $default_cache
	if (~ $"handle '') { parse_feeds $"cache/*.gmi | 9 sort -ur +2 }
	if not { parse_feeds $"cache/$"handle@*.gmi | 9 sort -ur +2 }
case render
	templates/sub.tpl.rc
case *
	echo gemsubs ls '[FEED_LIST]' >[1=2]
	echo gemsubs cache '[CACHE]' >[1=2]
	echo gemsubs cron '[FEED_LIST]' '[CACHE]'>[1=2]
	echo gemsubs feed '[CACHE]' >[1=2]
	echo gemsubs view '[HANDLE]' '[CACHE]' >[1=2]
}

cron

reference docs

[ ] gemini protocol spec

[ ] gemini protocol best practices

[ ] titan protocol spec? [1]

[ ] titan protocol spec? [2]

demo gempub fetch script