Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,7 @@ store

*.key

# Don't commit our internal ansibles!
ansible/prod.yml
ansible/staging.yml
ansible/mauve.yml
33 changes: 33 additions & 0 deletions @types/bt-fetch.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
declare module 'bt-fetch' {
export type TorrentManagerOptions = Partial<{
folder: string
timeout: number
reloadInterval: number
torrentPort: number
}>

export interface Torrent {
infoHash: Buffer
publicKey: Buffer
}

export type TorrentPublishOpts = Partial<{
name: string
comment: string
createdBy: string
creationDate: string
}>

export interface KeyPair {
publicKey: string
secretKey: string
}

export class TorrentManager {
constructor (opts: TorrentManagerOptions)
stopSeedingPublicKey (publicKey: string): Promise<boolean>
republishPublicKey (publicKey: string, secretKey: string, opts: TorrentPublishOpts): Promise<Torrent>
createKeypair (petname?: string): KeyPair
destroy (): Promise<void>
}
}
2 changes: 1 addition & 1 deletion ansible/roles/distributed_press/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ distributed_press_host: "localhost"
distributed_press_ipfs_provider: "builtin"

distributed_press_git_repo: "https://github.com/hyphacoop/api.distributed.press.git"
distributed_press_git_branch: "v1.0.0"
distributed_press_git_branch: "v1.1.0"
distributed_press_source: "{{distributed_press_home}}/api.distributed.press"

distributed_press_domain: "example.com"
Expand Down
6 changes: 6 additions & 0 deletions ansible/roles/distributed_press/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@
- name: "Enable libp2p tcp traffic through firewall"
shell: "ufw allow in 7976/tcp"

- name: "Enable webtorrent udp traffic through firewall"
shell: "ufw allow in 2867/udp"

- name: "Enable webtorrent tcp traffic through firewall"
shell: "ufw allow in 2867/tcp"

- name: "Check if JWT keys got generated already"
stat:
path: "{{distributed_press_data}}/keys/"
Expand Down
3 changes: 3 additions & 0 deletions api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ async function apiBuilder (cfg: APIConfig): Promise<FastifyTypebox> {
hyper: {
path: path.join(protocolStoragePath, 'hyper')
},
bittorrent: {
path: path.join(protocolStoragePath, 'bittorrent')
},
http: {
path: path.join(protocolStoragePath, 'http')
}
Expand Down
12 changes: 10 additions & 2 deletions api/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,21 @@ export const IPFSProtocolFields = GenericProtocol(Type.Object({
pubKey: Type.String(), // ipns://{publishKey}
dnslink: Type.String()
}))
export const BitTorrentProtocolFields = GenericProtocol(Type.Object({
gateway: Type.String(), // same as gateway in HyperProtocolFields
magnet: Type.String(), // Used by most torrent clients. Note: Will not update in regular clients
infoHash: Type.String(), // Immutable link, similar to ipfs public key
pubKey: Type.String(), // Link to public key for BEP-46, similar to IPNS
dnslink: Type.String()
}))

export const Protocols = Type.Object({
http: HTTPProtocolFields,
hyper: HyperProtocolFields,
ipfs: IPFSProtocolFields
ipfs: IPFSProtocolFields,
bittorrent: BitTorrentProtocolFields
})
export const ProtocolStatus = Type.Record(Type.KeyOf(Protocols), Type.Boolean())
export const ProtocolStatus = Type.Partial(Type.Record(Type.KeyOf(Protocols), Type.Boolean()))
export const Site = Type.Object({
id: Type.String(),
domain: Type.String(),
Expand Down
3 changes: 2 additions & 1 deletion config/sites.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ test('sites are default private', async t => {
protocols: {
http: true,
ipfs: false,
hyper: false
hyper: false,
bittorrent: false
}
})
const result = await cfg.get(site.id)
Expand Down
30 changes: 26 additions & 4 deletions config/sites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class SiteConfigStore extends Config<Static<typeof Site>> {
const site = await this.get(siteId)

const promises = []
if (site.protocols.http) {
if (site.protocols.http === true) {
const promise = this.protocols.http
.sync(siteId, filePath, undefined, ctx)
.then((protocolLinks) => {
Expand All @@ -43,7 +43,7 @@ export class SiteConfigStore extends Config<Static<typeof Site>> {
promises.push(promise)
}

if (site.protocols.hyper) {
if (site.protocols.hyper === true) {
const promise = this.protocols.hyper
.sync(siteId, filePath, undefined, ctx)
.then((protocolLinks) => {
Expand All @@ -53,7 +53,7 @@ export class SiteConfigStore extends Config<Static<typeof Site>> {
promises.push(promise)
}

if (site.protocols.ipfs) {
if (site.protocols.ipfs === true) {
const promise = this.protocols.ipfs
.sync(siteId, filePath, undefined, ctx)
.then((protocolLinks) => {
Expand All @@ -63,6 +63,16 @@ export class SiteConfigStore extends Config<Static<typeof Site>> {
promises.push(promise)
}

if (site.protocols.bittorrent === true) {
const promise = this.protocols.bittorrent
.sync(siteId, filePath, undefined, ctx)
.then((protocolLinks) => {
site.links.bittorrent = protocolLinks
})

promises.push(promise)
}

await Promise.all(promises)
await this.db.put(siteId, site)
}
Expand All @@ -78,7 +88,19 @@ export class SiteConfigStore extends Config<Static<typeof Site>> {
}

async get (id: string): Promise<Static<typeof Site>> {
return await this.db.get(id)
const site = await this.db.get(id)
const TO_FILL = ['bittorrent', 'public']
/* eslint-disable */
for (const key of TO_FILL) {
// @ts-ignore
if (!site[key]) {
// @ts-ignore
site[key] = false
}
}
/* eslint-enable */

return site
}

async listAll (hidePrivate: boolean): Promise<string[]> {
Expand Down
4 changes: 3 additions & 1 deletion dns/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ test('basic dns resolve', async t => {
protocols: {
http: false,
ipfs: true,
hyper: true
hyper: true,
bittorrent: true
},
public: true
})
Expand All @@ -42,6 +43,7 @@ test('basic dns resolve', async t => {
const response = await dnsClient.query(`_dnslink.${site.domain}`, 'TXT')
t.true(hasAnswer(response, 'ipns'), 'returned dns query has an ipns entry')
t.true(hasAnswer(response, 'hyper'), 'returned dns query has a hyper entry')
t.true(hasAnswer(response, 'bittorrent'), 'returned dns query has a bittorrent entry')
t.is(response.answers.filter(ans => ans.type !== DNS.Packet.TYPE.TXT).length, 0, 'should not include any non-TXT entries')
})

Expand Down
9 changes: 9 additions & 0 deletions dns/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ export async function initDnsServer (port: number, store: SiteConfigStore, logge
data: `dnslink=${links.hyper.dnslink}`
})
}
if (links.bittorrent !== undefined) {
response.answers.push({
name,
type: dns2.Packet.TYPE.TXT,
class: dns2.Packet.CLASS.IN,
ttl: 60,
data: `dnslink=${links.bittorrent.dnslink}`
})
}
send(response)
})
.catch((error) => {
Expand Down
20 changes: 19 additions & 1 deletion fixtures/mockProtocols.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { Static, TSchema } from '@sinclair/typebox'
import { HTTPProtocolFields, HyperProtocolFields, IPFSProtocolFields } from '../api/schemas.js'
import { HTTPProtocolFields, HyperProtocolFields, IPFSProtocolFields, BitTorrentProtocolFields } from '../api/schemas.js'
import { ProtocolManager } from '../protocols/index.js'
import Protocol, { Ctx, SyncOptions } from '../protocols/interfaces.js'

export class MockProtocolManager implements ProtocolManager {
http: MockHTTPProtocol
ipfs: MockIPFSProtocol
hyper: MockHyperProtocol
bittorrent: MockBitTorrentProtocol

constructor () {
this.ipfs = new MockIPFSProtocol()
this.http = new MockHTTPProtocol()
this.hyper = new MockHyperProtocol()
this.bittorrent = new MockBitTorrentProtocol()
}

async load (): Promise<void> {
const promises = [
this.ipfs.load(),
this.hyper.load(),
this.bittorrent.load(),
this.http.load()
]
await Promise.all(promises)
Expand All @@ -27,6 +30,7 @@ export class MockProtocolManager implements ProtocolManager {
const promises = [
this.ipfs.unload(),
this.hyper.unload(),
this.bittorrent.unload(),
this.http.unload()
]
await Promise.all(promises)
Expand Down Expand Up @@ -81,3 +85,17 @@ class MockHyperProtocol extends BaseMockProtocol<typeof HyperProtocolFields> {
}
}
}

class MockBitTorrentProtocol extends BaseMockProtocol<typeof BitTorrentProtocolFields> {
async sync (_id: string, _folderPath: string, _options?: SyncOptions, _ctx?: Ctx): Promise<Static<typeof BitTorrentProtocolFields>> {
return {
enabled: true,
link: 'bittorrent://example-link',
gateway: 'https://example-bittorrent-gateway/example-link',
dnslink: '/bittorrent/example-raw',
infoHash: 'bittorrent://example-link-infohash',
pubKey: 'bittorrent://example-link-publickey',
magnet: 'magnet:?xt:urn:btih:example-link&xs=urn:btpk:example-link'
}
}
}
3 changes: 2 additions & 1 deletion fixtures/siteConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export const exampleSiteConfig: Static<typeof NewSite> = {
protocols: {
http: true,
ipfs: false,
hyper: false
hyper: false,
bittorrent: false
},
public: true
}
Loading