on 2a2f4f8 help sign in
webring/scripts/hallway.js
134 lines 3.8 kB history raw
1'use strict'
3function Hallway (sites) {
4 const feeds = {}
5 this.sites = sites
6 this.el = document.createElement('div')
7 this.el.id = 'hallway'
9 this.install = function (host) {
10 host.appendChild(this.el)
11 // Find feeds
12 this.findFeeds()
13 }
15 this.start = function () {
16 this.el.innerHTML = 'hello'
17 this.fetchFeeds()
18 // this.fetch('https://wiki.xxiivv.com/twtxt.txt')
19 }
21 this.refresh = function () {
22 const entries = this.sortEntries()
23 let html = ''
24 for (const id in entries) {
25 html += `${this.templateEntry(entries[id])}\n`
26 }
27 this.el.innerHTML = `<ul>${html}</ul>${this._footer()}`
28 }
30 // Entries
32 this.sortEntries = function () {
33 const a = []
34 for (const id in feeds) {
35 const feed = feeds[id]
36 for (const i in feed.content) {
37 const entry = feed.content[i]
38 a.push(entry)
39 }
40 }
41 return a
42 }
44 this.templateEntry = function (entry) {
45 // Find mention
46 if (entry.body.indexOf('@<') > -1) {
47 const data = entry.body.split('@<').pop().split('>')[0]
48 const mention = data.split(' ')
49 const name = mention[0]
50 const path = mention[1]
51 entry.body = entry.body.replace(`@<${data}>`, `<a href='${path}'>${name}</a>`)
52 }
54 return `<li class='entry'><span class='date'>${timeAgo(Date.parse(entry.date))}</span> <span class='author'>${entry.author}</span> <span class='body'>${entry.body}</span></li>`
55 }
57 // Feeds
59 this.findFeeds = function () {
60 console.log('Finding feeds..')
61 for (const id in sites) {
62 const site = sites[id]
63 if (site.feed && site.author) {
64 feeds[site.author] = { path: site.feed }
65 }
66 }
67 console.log(`Found ${Object.keys(feeds).length} feeds.`)
68 }
70 this.fetchFeeds = function () {
71 console.log(`Fetching ${Object.keys(feeds).length} feeds..`)
72 for (const id in feeds) {
73 this.fetchFeed(id, feeds[id])
74 }
75 }
77 this.fetchFeed = function (id, feed) {
78 console.log(`Fetching ${id}(${feed.path})..`)
79 Promise.all([ fetch(feed.path + '?v=1', { cache: 'no-store' }).then(x => x.text()) ]).then(([content]) => {
80 feeds[id].content = parseFeed(id, content)
81 this.refresh()
82 })
83 }
85 // Extras
87 this._footer = function () {
88 return '<p>The <b>Hallway</b> is a decentralized forum, to join the conversation, simply create yourself a <a href="https://twtxt.readthedocs.io/en/stable/user/twtxtfile.html">twtxt</a> feed and <a href="https://github.com/XXIIVV/Webring/">add it</a> to your entry in the webring.</p>'
89 }
91 // Utils
93 function parseFeed (author, feed) {
94 const lines = feed.split('\n')
95 const entries = []
96 for (const id in lines) {
97 const line = lines[id]
98 const date = line.substr(0, 25).trim()
99 const body = line.substr(26).trim()
100 entries.push({ date, body, author })
101 }
102 return entries
103 }
105 function timeAgo (dateParam) {
106 if (!dateParam) {
107 return null
108 }
110 const date = typeof dateParam === 'object' ? dateParam : new Date(dateParam)
111 const DAY_IN_MS = 86400000 // 24 * 60 * 60 * 1000
112 const today = new Date()
113 const yesterday = new Date(today - DAY_IN_MS)
114 const seconds = Math.round((today - date) / 1000)
115 const minutes = Math.round(seconds / 60)
116 const isToday = today.toDateString() === date.toDateString()
117 const isYesterday = yesterday.toDateString() === date.toDateString()
119 if (seconds < 5) {
120 return 'now'
121 } else if (seconds < 60) {
122 return `${seconds} seconds ago`
123 } else if (seconds < 90) {
124 return 'about a minute ago'
125 } else if (minutes < 60) {
126 return `${minutes} minutes ago`
127 } else if (isToday) {
128 return `${Math.floor(minutes / 60)} hours ago`
129 } else if (isYesterday) {
130 return 'yesterday'
131 }
132 return `${Math.floor(minutes / 1440)} days ago`
133 }