on edbec08 help sign in
webring/scripts/hallway.js
143 lines 4.0 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 this.findFeeds()
12 }
14 this.start = function () {
15 this.el.innerHTML = 'hello'
16 this.fetchFeeds()
17 }
19 this.refresh = function () {
20 const entries = this.sortEntries()
21 let html = ''
22 for (const id in entries) {
23 html += `${this.templateEntry(entries[id])}\n`
24 }
25 this.el.innerHTML = `<ul>${html}</ul>${this._footer()}`
26 }
28 // Entries
30 function compare( a, b ) {
31 if ( a.date < b.date ){
32 return -1;
33 }
34 if ( a.date > b.date ){
35 return 1;
36 }
37 return 0;
38 }
40 this.sortEntries = function () {
41 const a = []
42 for (const id in feeds) {
43 const feed = feeds[id]
44 for (const i in feed.content) {
45 const entry = feed.content[i]
46 a.push(entry)
47 }
48 }
49 return a.sort( compare );
50 }
52 this.templateEntry = function (entry) {
53 // Find mention
54 if (entry.body.indexOf('@<') > -1) {
55 const data = entry.body.split('@<').pop().split('>')[0]
56 const mention = data.split(' ')
57 const name = mention[0]
58 const path = mention[1]
59 entry.body = entry.body.replace(`@<${data}>`, `<a href='${path}'>@${name}</a>`)
60 }
62 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>`
63 }
65 // Feeds
67 this.findFeeds = function () {
68 console.log('Finding feeds..')
69 for (const id in sites) {
70 const site = sites[id]
71 if (site.feed && site.author) {
72 feeds[site.author] = { path: site.feed }
73 }
74 }
75 console.log(`Found ${Object.keys(feeds).length} feeds.`)
76 }
78 this.fetchFeeds = function () {
79 console.log(`Fetching ${Object.keys(feeds).length} feeds..`)
80 for (const id in feeds) {
81 this.fetchFeed(id, feeds[id])
82 }
83 }
85 this.fetchFeed = function (id, feed) {
86 console.log(`Fetching ${id}(${feed.path})..`)
87 Promise.all([ fetch(feed.path + '?v=1', { cache: 'no-store' }).then(x => x.text()) ]).then(([content]) => {
88 feeds[id].content = parseFeed(id, content)
89 this.refresh()
90 })
91 }
93 // Extras
95 this._footer = function () {
96 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 <a href="index.html">webring</a>.</p>'
97 }
99 // Utils
101 function parseFeed (author, feed) {
102 const lines = feed.split('\n')
103 const entries = []
104 for (const id in lines) {
105 const line = lines[id].trim()
106 if(line === ''){ continue }
107 const date = line.substr(0, 25).trim()
108 const body = line.substr(26).trim()
109 entries.push({ date, body, author })
110 }
111 return entries
112 }
114 function timeAgo (dateParam) {
115 if (!dateParam) {
116 return null
117 }
119 const date = typeof dateParam === 'object' ? dateParam : new Date(dateParam)
120 const DAY_IN_MS = 86400000 // 24 * 60 * 60 * 1000
121 const today = new Date()
122 const yesterday = new Date(today - DAY_IN_MS)
123 const seconds = Math.round((today - date) / 1000)
124 const minutes = Math.round(seconds / 60)
125 const isToday = today.toDateString() === date.toDateString()
126 const isYesterday = yesterday.toDateString() === date.toDateString()
128 if (seconds < 5) {
129 return 'now'
130 } else if (seconds < 60) {
131 return `${seconds} seconds ago`
132 } else if (seconds < 90) {
133 return 'about a minute ago'
134 } else if (minutes < 60) {
135 return `${minutes} minutes ago`
136 } else if (isToday) {
137 return `${Math.floor(minutes / 60)} hours ago`
138 } else if (isYesterday) {
139 return 'yesterday'
140 }
141 return `${Math.floor(minutes / 1440)} days ago`
142 }