Home

Awesome

<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

Table of Contents generated with DocToc

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

libfritter

Data definitions and methods for Fritter, a Twitter clone built on top of Dat. Uses WebDB to read and write records on the Dat network.

See the Fritter app to see this library in use.

const LibFritter = require('@beaker/libfritter')
const fritter = new LibFritter()
await fritter.db.open()
await fritter.db.indexArchive('dat://bob.com')
await fritter.social.getProfile('dat://bob.com') // => ...

Schemas:

Usage

Getting started

LibFritter provides a set of methods to be used on top of a WebDB instance.

Setup will always include the following steps:

// create the libfritter instance
const fritter = new LibFritter()
// open the webdb
await fritter.db.open()

WebDB maintains an index which will determine who shows up in the feed, and whether any read method works for a given archive. (For instance, you can't call getProfile() on an archive that hasn't been indexed.) You can manage the index's membership using WebDB's methods:

// add a user
await fritter.db.indexArchive('dat://bob.com')
// remove a user
await fritter.db.unindexArchive('dat://bob.com')

You can also add individual files to the index, which is helpful when the user navigates to a thread:

// add an individual file
await fritter.db.indexFile('dat://bob.com/posts/1.json')

When you create a dat archive for the local user, you'll want to call prepareArchive() to setup the folder structure:

var alice = DatArchive.create({title: 'Alice', description: 'My Fritter profile'})
await fritter.prepareArchive(alice)

Profiles

User profiles include a name, bio, and an avatar image.

await fritter.social.setProfile(alice, {
  name: 'Alice',
  bio: 'A cool hacker'
})

await fritter.social.setAvatar(alice, 'iVBORw...rkJggg==', 'png')

await fritter.social.getProfile(alice) /* => {
  name: 'Alice',
  bio: 'A cool hacker',
  avatar: '/avatar.png'
} */

Social

Every user maintains a public list of other users they follow. You can modify and examine the social graph using these methods.

await fritter.social.follow(alice, bob)
await fritter.social.follow(alice, 'dat://bob.com') // (urls work too)
await fritter.social.listFollowers(bob) // => [{name: 'Alice', bio: 'A cool hacker', ...}]

Feed

The feed contains simple text-based posts.

// posting a new thread
await fritter.feed.post(alice, {
  text: 'Hello, world!',
})

// posting a reply
await fritter.feed.post(alice, {
  text: 'Hello, world!',
  threadParent: parent.getRecordURL(), // url of message replying to
  threadRoot: root.getRecordURL(), // url of topmost ancestor message
  createdAt: Date.parse('04 Dec 2017 00:12:00 GMT') // optional 
})

The list method will show any indexed posts.

await fritter.feed.listPosts({
  fetchAuthor: true,
  countVotes: true,
  reverse: true,
  rootPostsOnly: true,
  countReplies: true
})

You can view the posts of an individual user by adding the author filter, and also narrow down the feed to only include the followed users using the authors filter.

Like / Unlike

Users can like posts using the votes.

await fritter.feed.vote(alice, {vote: 1, subject: 'dat://bob.com/posts/1.json'})
await fritter.feed.listVotesFor('dat://bob.com/posts/1.json') /* => {
  up: 1,
  down: 0,
  value: 1,
  upVoters: ['dat://alice.com']
}

Notifications

You can view recent notifications (mentions, likes and replies on your posts) using the notifications api.

await fritter.notifications.listNotifications() /* => [
  { type: 'mention',
    url: 'dat://bob.com/posts/0jc7w0d5cd.json',
    createdAt: 15155171572345 },
  { type: 'reply',
    url: 'dat://alice.com/posts/0jc7w07be.json',
    createdAt: 1515517526289 },
  { type: 'vote',
    vote: 1,
    subject: 'dat://alice.com/posts/0jc7w079o.json',
    origin: 'dat://bob.com',
    createdAt: 1515517526308 }
]*/

API

new LibFritter([opts])

const fritter = new LibFritter()

Create a new LibFritter instance. The mainIndex will control where the indexes are stored. You can specify different names to run multiple LibFritter instances at once.

fritter.db

The WebDB instance.

fritter.setUser(archive)

fritter.setUser(alice)

Sets the local user. Used in notifications to know which posts should be indexed.

fritter.prepareArchive(archive)

await fritter.prepareArchive(alice)

Create needed folders for writing to an archive. This should be called on any archive that represents the local user.

fritter.social.getProfile(archive)

await fritter.social.getProfile(alice) // => {name: 'Alice', bio: 'A cool hacker', avatar: '/avatar.png'}

Get the profile data of the given archive.

fritter.social.setProfile(archive, profile)

await fritter.social.setProfile(alice, {name: 'Alice', bio: 'A cool hacker'})

Set the profile data of the given archive.

fritter.social.setAvatar(archive, imgDataBuffer, extension)

await fritter.social.setAvatar(alice, myPngData, 'png')

Set the avatar image of the given archive.

fritter.social.follow(archive, targetUser[, targetUserName])

await fritter.social.follow(alice, bob, 'Bob')

Add to the follow-list of the given archive.

fritter.social.unfollow(archive, targetUser)

await fritter.social.unfollow(alice, bob)

Remove from the follow-list of the given archive.

fritter.social.listFollowers(archive)

await fritter.social.listFollowers(alice)

List users in db that follow the given archive.

fritter.social.countFollowers(archive)

await fritter.social.countFollowers(alice)

Count users in db that follow the given archive.

fritter.social.listFriends(archive)

await fritter.social.listFriends(alice)

List users in db that mutually follow the given archive.

fritter.social.countFriends(archive)

await fritter.social.countFriends(alice)

Count users in db that mutually follow the given archive.

fritter.social.isFollowing(archiveA, archiveB)

await fritter.social.isFollowing(alice, bob) // => true

Test if archiveA is following archiveB.

fritter.social.isFriendsWith(archiveA, archiveB)

await fritter.social.isFriendsWith(alice, bob) // => true

Test if archiveA and archiveB are mutually following each other.

fritter.feed.post(archive, post)

// posting a new thread
await fritter.feed.post(alice, {
  text: 'Hello, world!',
})

// posting a reply
await fritter.feed.post(alice, {
  text: 'Hello, world!',
  threadParent: parent.getRecordURL(), // url of message replying to
  threadRoot: root.getRecordURL() // url of topmost ancestor message
})

Post a new message to the feed.

fritter.feed.listPosts([opts])

await fritter.feed.listPosts({limit: 30})

Fetch a list of posts in the feed index.

fritter.feed.countPosts([opts])

await fritter.feed.countPosts({author: alice})

Count posts in the feed index.

fritter.feed.getThread(url[, opts])

await fritter.feed.getThread('dat://alice.com/posts/1.json')

Fetch a discussion thread, including all replies.

fritter.feed.vote(archive, data)

await fritter.feed.vote(alice, {
  vote: 1,
  subject: 'dat://bob.com/posts/1.json'
})

Publish a vote on the given subject.

fritter.feed.listVotesFor(subject)

await fritter.feed.listVotesFor('dat://bob.com/posts/1.json')

Returns a vote tabulation of the given subject.

fritter.notifications.listNotifications([opts])

await fritter.notifications.listNotifications({limit: 30})

Fetch a list of events in the notifications index.

fritter.notifications.countNotifications([opts])

await fritter.notifications.countNotifications()

Fetch a count of events in the notifications index.