mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-03-12 21:48:39 +01:00
developing...
This commit is contained in:
parent
110000beef
commit
00593e9e44
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
node_modules/
|
example_user/
|
||||||
|
server/node_modules/
|
||||||
test/
|
test/
|
||||||
|
45
README.md
45
README.md
@ -68,8 +68,7 @@ __Administrations can be a lot more than filters:__
|
|||||||
|
|
||||||
An administration can personalize almost everything in how content is viewed, what content is allowed (acting a filter), whitelists, blacklists, eventually even the CSS or Layout of the front page, post tags and a lot more.
|
An administration can personalize almost everything in how content is viewed, what content is allowed (acting a filter), whitelists, blacklists, eventually even the CSS or Layout of the front page, post tags and a lot more.
|
||||||
|
|
||||||
`admin` is the administrator of the repo. He decides the rules. He can name moderators and their modifications
|
`admin` is the administrator of the repo. He decides the rules.
|
||||||
will be merged with his boards' profile by his Admin Node.
|
|
||||||
|
|
||||||
You (the user) will be able to choose a main _administration_ for a board and then also include content from other administrations.
|
You (the user) will be able to choose a main _administration_ for a board and then also include content from other administrations.
|
||||||
|
|
||||||
@ -93,7 +92,7 @@ If this gets implemented it should go in the Admin Node.
|
|||||||
__About private boards__
|
__About private boards__
|
||||||
|
|
||||||
They probably will be possible but are not included for now, because hidden content is far away in the IPFS roadmap.
|
They probably will be possible but are not included for now, because hidden content is far away in the IPFS roadmap.
|
||||||
Administration can forbit people to write, but not to read.
|
Administrations can forbit people to write, but not to read.
|
||||||
|
|
||||||
__Important Note:__ due to how the system works, an _administration_'s rules and decisions are just _guidelines_ for your computer.
|
__Important Note:__ due to how the system works, an _administration_'s rules and decisions are just _guidelines_ for your computer.
|
||||||
Your computer will always be able to choose what to see and what to hide, it just uses your administration's guidelines _by default_.
|
Your computer will always be able to choose what to see and what to hide, it just uses your administration's guidelines _by default_.
|
||||||
@ -104,12 +103,14 @@ That's why there are __Cache Servers__.
|
|||||||
They monitor _administrations_ and cache all the content (or some of it) as soon as it becomes available on the network, making sure it never gets lost.
|
They monitor _administrations_ and cache all the content (or some of it) as soon as it becomes available on the network, making sure it never gets lost.
|
||||||
They are completely optional but they help out in serving the users.
|
They are completely optional but they help out in serving the users.
|
||||||
|
|
||||||
|
Cache servers also act as gateways and provide an HTTP API to access the boards.
|
||||||
|
|
||||||
Also note that due to how IPFS works, the more popular some content gets, the _faster it downloads_ and the _easier it is for your computer to find it_. Censorship is impractical in such a system and data is almost impossible to take down. That's why IPFS is also called _the
|
Also note that due to how IPFS works, the more popular some content gets, the _faster it downloads_ and the _easier it is for your computer to find it_. Censorship is impractical in such a system and data is almost impossible to take down. That's why IPFS is also called _the
|
||||||
permanent web_.
|
permanent web_.
|
||||||
|
|
||||||
## Faq
|
## Faq
|
||||||
|
|
||||||
#### Can I be anonymous?
|
#### Can I be anonymous?
|
||||||
|
|
||||||
What if someone monitors my IPFS node? Will they know what content I'm seeing and everything I post and link it to my IP?
|
What if someone monitors my IPFS node? Will they know what content I'm seeing and everything I post and link it to my IP?
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ __Yes, but there is a solution.__
|
|||||||
|
|
||||||
You can access a Cache Server's HTTP(s) gateway via Tor for read only access to content.
|
You can access a Cache Server's HTTP(s) gateway via Tor for read only access to content.
|
||||||
|
|
||||||
To post while mantaining anonimity, you would need to run IPFS via Tor. This is probably not easily done at the moment but [it is planned](
|
To post while mantaining anonimity, you would need to run IPFS via Tor. This is probably not easily done at the moment but it is planned.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
@ -141,25 +142,30 @@ Each user exposes via IPNS a folder containing:
|
|||||||
|
|
||||||
- boards
|
- boards
|
||||||
- _board name(s)_
|
- _board name(s)_
|
||||||
|
- settings.json - the board's settings
|
||||||
|
- whitelist - contains links to all whitelisted users
|
||||||
|
- blacklist - contains links to all blacklisted users
|
||||||
|
- approved - contains links to all approved content
|
||||||
- posts
|
- posts
|
||||||
- _board name(s)_
|
- _board name(s)_
|
||||||
- _admin name(s)_
|
- _post(s)_
|
||||||
- _post(s)_
|
|
||||||
- comments
|
- comments
|
||||||
- _board name(s)_
|
- _board name(s)_
|
||||||
- _admin name(s)_
|
- _comment(s)_
|
||||||
- _comment(s)_
|
|
||||||
- votes
|
- votes
|
||||||
- _board name(s)_
|
- _board name(s)_
|
||||||
- _admin name(s)_
|
- _vote(s)_
|
||||||
- _vote(s)_
|
- name - stores the user's screen name (also stored in profile?)
|
||||||
- compatibility: could be used to store compatibility information
|
- profile.json - user's additional profile data
|
||||||
|
- ipfs-boards-version.txt - used to store compatibility information
|
||||||
|
|
||||||
#### Post
|
#### Post
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "Title of the post",
|
"title": "Title of the post",
|
||||||
"date": "date of the post",
|
"date": "date of the post",
|
||||||
|
"op": "id_of_the_original_poster",
|
||||||
|
"preference": "id_of_the_preferred_administration",
|
||||||
"text": "Content of the post"
|
"text": "Content of the post"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,16 +174,21 @@ possible for lange texts without duplicating data.
|
|||||||
|
|
||||||
#### Comment
|
#### Comment
|
||||||
|
|
||||||
Comment text
|
{
|
||||||
|
"parent": "id_of_the_parent_object",
|
||||||
|
"date": "date of the comment"
|
||||||
|
"preference": "id_of_the_preferred_administration",
|
||||||
|
"op": "id_of_the_original_poster",
|
||||||
|
"text": "Content of the post"
|
||||||
|
}
|
||||||
|
|
||||||
#### Vote
|
#### Vote
|
||||||
|
|
||||||
ipfs-board:vote-for:object_url
|
ipfs:boards:vote-for:object_url
|
||||||
|
|
||||||
### Versioning
|
#### Versioning
|
||||||
|
|
||||||
a `version` file or something should be included in the user's files to ensure compatibility between different
|
just the version ID written in the version file
|
||||||
versions or forks.
|
|
||||||
|
|
||||||
### License
|
### License
|
||||||
|
|
||||||
|
138
lib/boards-api.js
Normal file
138
lib/boards-api.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// Write an API to aggregate data without duplication and making accessing content easy. Use the IPFS http api
|
||||||
|
|
||||||
|
function asObj(str,done){
|
||||||
|
var obj
|
||||||
|
try {
|
||||||
|
obj = JSON.parse(str)
|
||||||
|
} catch (e) {
|
||||||
|
done(e,null)
|
||||||
|
}
|
||||||
|
if(obj != undefined) done(null,obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
function replyAsObj(res,isJson,done){
|
||||||
|
if(res.readable){
|
||||||
|
// Is a stream
|
||||||
|
res.setEncoding('utf8')
|
||||||
|
var data = ''
|
||||||
|
res.on('data',d => {
|
||||||
|
data += d
|
||||||
|
})
|
||||||
|
res.on('end',() => {
|
||||||
|
if(isJson) {
|
||||||
|
asObj(data,done)
|
||||||
|
} else {
|
||||||
|
done(null,data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Is a string
|
||||||
|
if(isJson){
|
||||||
|
asObj(res,done)
|
||||||
|
} else {
|
||||||
|
done(null,res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function BoardsAPI(ipfs){
|
||||||
|
this.ipfs = ipfs
|
||||||
|
this.version = 'dev'
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.searchUsers = function(done){
|
||||||
|
// Look at our peers
|
||||||
|
this.ipfs.swarm.peers(function(err,r){
|
||||||
|
var peers = r.Strings.forEach(function(s){
|
||||||
|
var ss = s.split('/')
|
||||||
|
var addr = ss[ss.length-1]
|
||||||
|
// Try to see if they run IPFS Boards
|
||||||
|
this.ipfs.cat(addr+'/ipfs-boards-version.txt',function(err,r){
|
||||||
|
if(err) return console.log('Search Err:',err)
|
||||||
|
replyAsObj(r,false,(_,res) => {
|
||||||
|
// He does!
|
||||||
|
// TODO: store found users in a list?
|
||||||
|
console.log('Found user:',addr,'using version',res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.getProfile = function(userID,done){
|
||||||
|
this.ipfs.cat(userID+'/profile.json',(err,res) => {
|
||||||
|
if(err){
|
||||||
|
done(err,null)
|
||||||
|
} else {
|
||||||
|
replyAsObj(res,true,done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.getName = function(userID,done){
|
||||||
|
this.ipfs.cat(userID+'/name',(err,res) => {
|
||||||
|
if(err){
|
||||||
|
done(err,null)
|
||||||
|
} else {
|
||||||
|
replyAsObj(res,false,done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.getBoardSettings = function(userID,board,done){
|
||||||
|
var url = userID+'/boards/'+board+'/settings.json'
|
||||||
|
this.ipfs.cat(url,function(err,res){
|
||||||
|
if(err){
|
||||||
|
done(err,{})
|
||||||
|
} else {
|
||||||
|
replyAsObj(res,true,done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.getBoardPosts(board,administratorID,done){
|
||||||
|
// Returns a stream
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.getUserPosts(user,board,done){
|
||||||
|
// Returns a stream
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.getComments(parent,board,done){
|
||||||
|
// Returns a stream
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.createPost(post,board,done){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.createComment(parent,comment,done){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardsAPI.prototype.createUpvote(parent,done){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// API for managing the administrations to be done later
|
||||||
|
|
||||||
|
// Initialize API
|
||||||
|
BoardsAPI.prototype.init = function(done){
|
||||||
|
this.ipfs.id( (err, res) => {
|
||||||
|
if(err){
|
||||||
|
console.log(err)
|
||||||
|
done(err)
|
||||||
|
} else {
|
||||||
|
console.log('I am',res.ID)
|
||||||
|
this.id = res.ID
|
||||||
|
console.log('Version is',this.version)
|
||||||
|
this.ipfs.add(new Buffer('ipfs:boards:version:'+this.version),(err,r) => {
|
||||||
|
this.version_hash = r[0].Hash
|
||||||
|
console.log('Version hash is',this.version_hash)
|
||||||
|
done(null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BoardsAPI
|
15
package.json
15
package.json
@ -2,13 +2,24 @@
|
|||||||
"name": "ipfs-board",
|
"name": "ipfs-board",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "decentralized discussion board",
|
"description": "decentralized discussion board",
|
||||||
"main": "server.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js"
|
"start": "node cli/server.js"
|
||||||
},
|
},
|
||||||
|
"bin": {
|
||||||
|
"ipfs-board": "cli/server.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+ssh://git@github.com/fazo96/ipfs-board.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/fazo96/ipfs-board/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/fazo96/ipfs-board#readme",
|
||||||
"author": "Enrico Fasoli (fazo96)",
|
"author": "Enrico Fasoli (fazo96)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"commander": "^2.9.0",
|
||||||
"express": "^4.13.3",
|
"express": "^4.13.3",
|
||||||
"ipfs-api": "^2.6.2"
|
"ipfs-api": "^2.6.2"
|
||||||
}
|
}
|
||||||
|
24
server.js
24
server.js
@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var ipfs = require('ipfs-api')('localhost','5001')
|
|
||||||
var express = require('express')
|
|
||||||
var app = express()
|
|
||||||
|
|
||||||
// Serve files in ./static
|
|
||||||
app.use(express.static('static'))
|
|
||||||
|
|
||||||
app.get('/@:user/:board',function(req,res){
|
|
||||||
ipfs.cat(req.params.user+'/'+req.params.board,function(err,res){
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// CatchAll route: serve the angular app
|
|
||||||
/*app.get('*',function(req,res){
|
|
||||||
res.sendFile(__dirname+'/static/index.html')
|
|
||||||
})*/
|
|
||||||
|
|
||||||
// Start http server
|
|
||||||
app.listen(3000,function(){
|
|
||||||
console.log('Started')
|
|
||||||
})
|
|
28
server/server.js
Executable file
28
server/server.js
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var ipfs = require('ipfs-api')('localhost','5001')
|
||||||
|
var BoardsAPI = require('../lib/boards-api.js')
|
||||||
|
var express = require('express')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
var boards = new BoardsAPI(ipfs)
|
||||||
|
|
||||||
|
// Serve web app
|
||||||
|
app.use(express.static('../webapp'))
|
||||||
|
|
||||||
|
// Create gateways to access the BoardsAPI
|
||||||
|
|
||||||
|
function startWebServer(){
|
||||||
|
// Start http server
|
||||||
|
app.listen(3000,function(){
|
||||||
|
console.log('Started Web Server')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
boards.init(function(err){
|
||||||
|
if(err){
|
||||||
|
console.log(err)
|
||||||
|
} else {
|
||||||
|
startWebServer()
|
||||||
|
}
|
||||||
|
})
|
@ -1,5 +1,3 @@
|
|||||||
console.log(require('ipfs-api'))
|
|
||||||
|
|
||||||
var boards = angular.module('boards',['ui.router'])
|
var boards = angular.module('boards',['ui.router'])
|
||||||
|
|
||||||
boards.config(function($stateProvider,$urlRouterProvider,$locationProvider){
|
boards.config(function($stateProvider,$urlRouterProvider,$locationProvider){
|
Loading…
Reference in New Issue
Block a user