Skip to content

Commit

Permalink
Updated setNotificationsReadTime and added the ascending parameter to…
Browse files Browse the repository at this point in the history
… the getPosts function
  • Loading branch information
baptistegreve committed Mar 31, 2023
1 parent 889b432 commit 646cbbd
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 31 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build decentralized social apps with the Orbis SDK
By using the Orbis SDK, developers can build their own decentralized social apps or add a decentralized social layer to their existing application in a very easy and performant way.
By using the Orbis SDK, developers can build their own decentralized social apps or add a decentralized social features to their existing application in a very easy and performant way.

## Why you should build on Orbis
By being built on top of Ceramic, Orbis offers many advantages to developers interested in building decentralized social applications:
Expand All @@ -14,7 +14,7 @@ By being built on top of Ceramic, Orbis offers many advantages to developers int
## Use cases
Here are some examples of applications that could be built on top of Orbis:

- Full social apps like [orbis.club](https://orbis.club)
- Full social apps like [orbis.club](https://app.orbis.club)
- Decentralized & encrypted messaging system
- Fully customizable & embedded group chat servers
- Decentralized Discourse governance forums
Expand All @@ -24,4 +24,4 @@ Here are some examples of applications that could be built on top of Orbis:
- And many other things...

## Documentation
Our documentation is available at https://orbis.club/developers
Our documentation is available at https://useorbis.com/documentation
134 changes: 108 additions & 26 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import {
sortByKey,
getAuthMethod,
getAddressFromDid,
resizeFile
resizeFile,
formatConversation
} from "./utils/index.js";
import { authenticatePkp } from "./utils/ceramic-helpers.js"

Expand All @@ -52,6 +53,9 @@ const postSchemaCommit = "k1dpgaqe3i64kjuyet4w0zyaqwamf9wrp1jim19y27veqkppo34ygh
const groupSchemaStream = "kjzl6cwe1jw1487a0xluwl3ip6lcdcfn8ahgomsbf8x5rf65mktdjuouz8xopbf";
const groupSchemaCommit = "k3y52l7qbv1fry2bramzfrq10z2vrywf96yk6n61d8ffsyzvs0k0wd68sanjjo16o";

const contextSchemaStream = "";
const contextSchemaCommit = "";

const channelSchemaStream = "kjzl6cwe1jw148ehiqrzh9npfr4kk4kyqd4as259yqzcr3i1dnrnm30ck5q0t6f";
const channelSchemaCommit = "k1dpgaqe3i64kjsvqaacts7pw2j419foun3d53gbyiv90gguufsv529yaq55rh0gmo68o5nft4ja7xmrtq9x1is59hn1ibx16d1e5wzg4tdxtutmegh2hy1a6";

Expand Down Expand Up @@ -662,17 +666,17 @@ export class Orbis {
}

/** Save the last read time for notifications for the connected user */
async setNotificationsReadTime(type, timestamp, context = null) {
async setNotificationsReadTime(options) {
let result;
if(context) {
if(options.context) {
/** Create tile with the settings details, including context */
result = await this.createTileDocument({
last_notifications_read_time: timestamp,
context: context
}, ["orbis", "settings", "notifications", type], notificationsReadSchemaCommit);
last_notifications_read_time: options.timestamp,
context: options.context
}, ["orbis", "settings", "notifications", options.type], notificationsReadSchemaCommit);
} else {
/** Create tile with the settings details */
result = await this.createTileDocument({last_notifications_read_time: timestamp}, ["orbis", "settings", "notifications", type], notificationsReadSchemaCommit);
result = await this.createTileDocument({last_notifications_read_time: options.timestamp}, ["orbis", "settings", "notifications", options.type], notificationsReadSchemaCommit);
}

/** Return confirmation results */
Expand Down Expand Up @@ -964,13 +968,9 @@ export class Orbis {
return result;
}

/** Update a post */
async updatePost(stream_id, body) {

}

/** Create a new conversation */
async createConversation(content) {

/** Make sure recipients field isn't empty */
if(!content || !content.recipients || content.recipients.length == 0) {
return {
Expand All @@ -980,20 +980,62 @@ export class Orbis {
}
}

/** Will format the conversation to return a clean content object */
/** Add sender to the list of recipients to make sure it can decrypt the messages as well */
let _content = {...content};
let recipients = _content.recipients;
recipients.push(this.session.id);
let _content = {...content};
let recipients = _content.recipients;
recipients.push(this.session.id);

/** If conversation has a name we encrypt oit */
if(content.name) {
let { accessControlConditions } = generateAccessControlConditionsForDMs(recipients);
let encryptedConversationName = await encryptString(content.name, "ethereum", accessControlConditions);
_content.encryptedName = encryptedConversationName;
_content.name = "";
}

/** Create tile */
let result = await this.createTileDocument(_content, ["orbis", "conversation"], conversationSchemaCommit);
let result = await this.createTileDocument(_content, ["orbis", "conversation"], conversationSchemaCommit, "orbis", true);

/** Return confirmation results */
return result;
}

/** Update an existing conversation */
async updateConversation(stream_id, content) {

/** Make sure recipients field isn't empty */
if(!content || !content.recipients || content.recipients.length == 0) {
return {
status: 300,
error: e,
result: "You can't update a conversations without recipients."
}
}

/** Will format the conversation to return a clean content object */
/** Add sender to the list of recipients to make sure it can decrypt the messages as well */
let _content = {...content};
let recipients = _content.recipients;
recipients.push(this.session.id);

/** If conversation has a name we encrypt oit */
if(content.name) {
let { accessControlConditions } = generateAccessControlConditionsForDMs(recipients);
let encryptedConversationName = await encryptString(content.name, "ethereum", accessControlConditions);
_content.encryptedName = encryptedConversationName;
_content.name = "";
}

/** Update tile */
let result = await this.updateTileDocument(stream_id, _content, ["orbis", "conversation"], conversationSchemaCommit, "orbis", true);

/** Return confirmation results */
return result;
}

/** Send a direct message in a conversation */
async sendMessage(content) {
async sendMessage(content, data) {
/** Require `message` */
if(!content || !content.body || content.body == undefined || content.body == "") {
return {
Expand Down Expand Up @@ -1055,6 +1097,11 @@ export class Orbis {
encryptedMessageSolana: encryptedMessageSolana
}

/** Add custom data field if any */
if(data) {
_content.data = data;
}

/** Create tile for this message */
let result = await this.createTileDocument(_content, ["orbis", "message"], messageSchemaCommit);
return result;
Expand Down Expand Up @@ -1160,20 +1207,42 @@ export class Orbis {
}
}

/** NOT AVAILABLE FOR NOW: Users can create or update a new context such as a group or a channel within a group to organize the posts being shared */
async createContext() {
/* Users can create a new context which can represent the project or app used by the developer */
async createContext(content) {
/** User must be connected to call this function. */
if(!this.session || !this.session.id) {
console.log("User must be connected to call this function. Make sure to call the connect or isConnected function and to use the same orbis object across your application.");
return({ data: null, error: "User must be connected to call this function." });
}

/** Try to create a new Orbis group stream */
let result = await this.createTileDocument(content, ["orbis", "context"], contextSchemaCommit);

/** Return confirmation results */
return result;
}
async updateContext() {

/** Will update an existing context */
async updateContext(stream_id, content) {
if(!stream_id) {
console.log("`stream_id` is required to update a context.");
return {
status: 300,
result: "`stream_id` is required to update a context."
}
}

/** Update TileDocument with new content */
let result = await this.updateTileDocument(stream_id, content, ["orbis", "context"], contextSchemaCommit);
return result;
}

/***********************
*** CERAMIC HELPERS ***
**********************/

/** Helper to create a basic TileDocument on Ceramic */
async createTileDocument(content, tags, schema, family = "orbis") {
async createTileDocument(content, tags, schema, family = "orbis", awaitIndex = false) {

/** User must be connected to call this function. */
if(!this.session || !this.session.id) {
Expand All @@ -1198,8 +1267,13 @@ export class Orbis {
},
);

/** Force index document */
forceIndex(doc.id.toString());
/** Await for indexing or not */
if(awaitIndex) {
await forceIndex(doc.id.toString());
} else {
forceIndex(doc.id.toString());
}


/** Return JSON with doc object */
res = {
Expand Down Expand Up @@ -1321,7 +1395,7 @@ export class Orbis {
* Retrieve posts shared in a specific context or by a specific user
* Returns an array of posts in the `data` field or an `error`.
*/
async getPosts(options, page = 0, limit = 50) {
async getPosts(options, page = 0, limit = 50, ascending = false) {
let query;

/** Default query for global feed, developers can pass an algorithm ID to order the posts */
Expand Down Expand Up @@ -1350,7 +1424,7 @@ export class Orbis {
query = this.api.rpc("all_posts_non_filtered").range(page * limit, (page + 1) * limit - 1);
break;
default:
query = this.api.from("orbis_v_posts").select().range(page * limit, (page + 1) * limit - 1).order('timestamp', { ascending: false });
query = this.api.from("orbis_v_posts").select().range(page * limit, (page + 1) * limit - 1).order('timestamp', { ascending: ascending });
break;
}
}
Expand All @@ -1364,7 +1438,7 @@ export class Orbis {
q_master: options?.master ? options.master : null,
q_include_child_contexts: options?.include_child_contexts ? options.include_child_contexts : false,
q_term: options?.term ? options.term : null
}).range(page * limit, (page + 1) * limit - 1).order('timestamp', { ascending: false });
}).range(page * limit, (page + 1) * limit - 1).order(options?.order_by ? options.order_by : 'timestamp', { ascending: ascending });
}

/** Query indexer */
Expand All @@ -1382,6 +1456,14 @@ export class Orbis {
return({ data, error, status });
}

/** Returns the details of a context */
async getContext(context_id) {
let { data, error, status } = await this.api.from("orbis_contexts").select().eq('stream_id', context_id).single();

/** Return results */
return({ data, error, status });
}

/** Get user reaction for a post */
async getReaction(post_id, did) {
let { data, error, status } = await this.api.from("orbis_reactions").select('type').eq('post_id', post_id).eq('creator', did);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@orbisclub/orbis-sdk",
"version": "0.4.35",
"version": "0.4.44",
"description": "Official package to implement quickly an Orbis powered decentralized social layer within your application.",
"author": "Baptiste Grève",
"license": "ISC",
Expand Down
20 changes: 19 additions & 1 deletion utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function forceIndex(stream_id) {
} else {
console.log("Error indexing stream " + stream_id + ":", res_final.result);
}
return;
return res_final;
} catch(e) {
console.log("Error indexing new stream: ", e);
return;
Expand All @@ -51,6 +51,24 @@ export async function fetchUserCredentials(did) {
}
}

/** Will format the conversation object for the createConversation and updateConversation objects */
export async function formatConversation(content) {
/** Add sender to the list of recipients to make sure it can decrypt the messages as well */
let _content = {...content};
let recipients = _content.recipients;
recipients.push(this.session.id);

/** If conversation has a name we encrypt oit */
if(content.name) {
let { accessControlConditions } = generateAccessControlConditionsForDMs(recipients);
let encryptedConversationName = await encryptString(content.name, "ethereum", accessControlConditions);
_content.encryptedName = encryptedConversationName;
_content.name = "";
}

return _content;
}

/** Generate a random seed that can be used to authenticate a new did:key */
export function randomSeed() {
const buffer = new Uint8Array(32);
Expand Down

0 comments on commit 646cbbd

Please sign in to comment.