@@ -15,59 +15,51 @@ var database;
1515// exit on failure
1616function prepareDatabase ( )
1717{
18- // load the database from file
19- database = new sqlite3 . Database ( config . dbFilename , sqlite3 . OPEN_READONLY , e => {
20- if ( e ) exit ( `Error opening database: ${ e } ` ) ;
21- } ) ;
18+ // load the database from file
19+ database = new sqlite3 . Database ( config . dbFilename , sqlite3 . OPEN_READONLY , e => {
20+ if ( e ) exit ( `Error opening database: ${ e } ` ) ;
21+ } ) ;
2222} ;
2323
2424// close the database if its open
2525function closeDatabase ( )
2626{
27- if ( database ) database . close ( ) . catch ( console . error ) ;
28- }
29-
30- // get a row in a table
31- function selectRow ( table , whereColumn , equals , callback )
32- {
33- // is this safe?
34- const sql = `SELECT * FROM ${ table } WHERE ${ whereColumn } = "${ equals } "` ;
35- database . all ( sql , [ ] , ( e , rows ) => {
36- if ( e ) exit ( `Error querying database: ${ e } ` ) ;
37- else callback ( rows ) ;
38- } ) ;
27+ if ( database ) database . close ( ) . catch ( console . error ) ;
3928}
4029
4130// take a timestamp and format it
4231function formatDate ( timestamp )
4332{
44- return new Date ( timestamp ) . toUTCString ( ) ;
33+ return new Date ( timestamp ) . toUTCString ( ) ;
4534}
4635
4736// format a massege for code blocks
4837function formatMessage ( string )
4938{
50- const regex = / \` \` \` ( ( [ a - z ] + ) \n ) ? \n * ( [ \s \S ] * ?) \n * \` \` \` / g;
51- return string . replace ( regex , ( match , p1 , p2 , p3 , offset , string ) =>
52- `<div class="code">${ p2 ? `<span class="lang">#${ p2 } </span><br />` : "" } ${ p3 } </div>` ) ;
39+ const regex = / \` \` \` ( ( [ a - z ] + ) \n ) ? \n * ( [ \s \S ] * ?) \n * \` \` \` / g;
40+ const s = string . replace ( regex , ( match , p1 , p2 , p3 , offset , string ) =>
41+ `<div class="code">${ p2 ? `<span class="lang">#${ p2 } </span><br />` : "" } ${ p3 . replace ( / \n / g, "<br />" ) } </div>` ) ;
42+ // also parse inline `code` and urls
43+ return s ;
5344}
5445
5546// make html output for a message
56- function makeMessagePage ( message , revisions )
47+ function makeMessagePage ( rows )
5748{
58- // just something for now, i don't know what we actually want to do
59- const header = `
60- <span class="field">Message ID:</span> <span class="value">${ message . msgId } </span><br />
61- <span class="field">Author:</span> <span class="value">${ message . author } </span><br />
62- <span class="field">Channel:</span> <span class="value">${ message . channel } </span><br />
63- ` ;
64- const body = revisions . map ( revision => `
49+ const body = rows . map ( row => `
50+ <a class="perma" href="/code?msgId=${ row . msgId } ">permalink</a><br />
51+ Author: ${ row . author } <br />
52+ Channel: ${ row . channel } <br />` + row . revisions . map ( revision => `
6553<span class="timestamp">${ formatDate ( revision . date ) } </span>
6654<div class="messageBody">${ formatMessage ( revision . fullMessage ) } </div>
67- ` ) . join ( "<br /><br />" ) ;
55+ ` ) . join ( "<br /><br />" ) ) . join ( "<br /><br />" ) ;
6856
69- return `
57+ return `
7058<style>
59+ .perma
60+ {
61+ font-size: small;
62+ }
7163.wrapper
7264{
7365 width: 400px;
@@ -108,60 +100,122 @@ function makeMessagePage(message, revisions)
108100</style>
109101
110102<div class="wrapper">
111- ${ header }
112- <br />
113103 ${ body }
114104</div>
115105 ` ;
116106}
117107
118- // request a message by id
119- frontend . get ( "/code/:id" , ( request , response ) => {
120- // select the message by id
121- selectRow ( "Message" , "msgId" , request . params . id , rows => {
122- if ( rows . length )
108+ // search page
109+ frontend . get ( "/" , ( request , response ) => {
110+ const sql = `SELECT DISTINCT author FROM Message` ;
111+ database . all ( sql , [ ] , ( e , authors ) => {
112+ if ( e ) exit ( `Error querying database: ${ e } ` ) ;
113+ else
114+ {
115+ const sql = `SELECT DISTINCT channel FROM Message` ;
116+ database . all ( sql , [ ] , ( e , channels ) => {
117+ if ( e ) exit ( `Error querying database: ${ e } ` ) ;
118+ else
123119 {
124- // assuming there's only one message per id
125- // as there should be
126- const message = rows [ 0 ] ;
127-
128- // select all the revisions of this message
129- selectRow ( "Content" , "associatedMsg" , message . msgId , rows => {
130- if ( rows . length )
131- {
132- // should we sort in sqlite instead of here?
133- // sort the revisions by timestamp
134- const sorted = rows . sort ( ( a , b ) => a . date - b . date ) ;
135-
136- // what should we actually be displaying here?
137- // a pretty display for the user?
138- // or some raw information?
139- // also, should we just show the most recent revision?
140- response . send ( makeMessagePage ( message , rows ) ) ;
141- }
142- else response . send ( "No revisions found!" ) ;
143- } ) ;
120+ response . send ( `
121+ <form action="/code/">
122+ <label for="author">Author</label>
123+ <select id="author" name="author">
124+ <option value="">*</option>
125+ ${ authors . map ( author => `<option value="${ author . author } ">${ author . author } </option>` ) . join ( "" ) }
126+ </select><br />
127+ <label for="channel">Channel</label>
128+ <select id="channel" name="channel">
129+ <option value="">*</option>
130+ ${ channels . map ( channel => `<option value="${ channel . channel } ">${ channel . channel } </option>` ) . join ( "" ) }
131+ </select><br />
132+ <label for="from">From</label>
133+ <input id="from" name="from" type="date"><br />
134+ <label for="to">To</label>
135+ <input id="to" name="to" type="date"><br />
136+ <input type="submit">
137+ </form>
138+ ` ) ;
144139 }
145- else response . send ( "Message not found!" ) ;
146- } ) ;
140+ } ) ;
141+ }
142+ } ) ;
143+ } ) ;
144+
145+ function strtotime ( string )
146+ {
147+ return new Date ( string ) . getTime ( ) ;
148+ }
149+
150+ // filter messages query
151+ frontend . get ( "/code/" , ( request , response ) => {
152+ var sql = `SELECT * FROM Message` ;
153+ const bindings = [ ] ;
154+
155+ var kw = "WHERE" ;
156+ if ( request . query . author )
157+ {
158+ sql += ` ${ kw } author = ?` ;
159+ bindings . push ( request . query . author ) ;
160+ kw = "AND" ;
161+ }
162+ if ( request . query . channel )
163+ {
164+ sql += ` ${ kw } channel = ?` ;
165+ bindings . push ( request . query . channel ) ;
166+ kw = "AND" ;
167+ }
168+ if ( request . query . msgId )
169+ {
170+ sql += ` ${ kw } msgId = ?` ;
171+ bindings . push ( request . query . msgId ) ;
172+ kw = "AND" ;
173+ }
174+
175+ database . all ( sql , bindings , ( e , messageRows ) => {
176+ if ( e ) exit ( `Error querying database: ${ e } ` ) ;
177+ else
178+ {
179+ const sql = `SELECT * FROM Content` ;
180+ database . all ( sql , [ ] , ( e , contentRows ) => {
181+ if ( e ) exit ( `Error querying database: ${ e } ` ) ;
182+ else
183+ {
184+ var rows = messageRows ;
185+ rows = rows . map ( row => {
186+ row . revisions = contentRows
187+ . filter ( revision => revision . associatedMsg === row . msgId ) ;
188+ delete row . revisions . associatedMsg ;
189+ return row ;
190+ } ) ;
191+ if ( request . query . from )
192+ rows = rows . filter ( row => row . revisions [ 0 ] . date >= strtotime ( request . query . from ) ) ;
193+ if ( request . query . to )
194+ rows = rows . filter ( row => row . revisions [ 0 ] . date < strtotime ( request . query . to ) ) ;
195+ if ( request . query . as === "json" ) response . send ( rows ) ;
196+ else response . send ( makeMessagePage ( rows ) ) ;
197+ } ;
198+ } ) ;
199+ } ;
200+ } ) ;
147201} ) ;
148202
149203// exit with error message
150204function exit ( message )
151205{
152- console . error ( message ) ;
153- closeDatabase ( ) ;
154- process . exit ( 1 ) ;
206+ console . error ( message ) ;
207+ closeDatabase ( ) ;
208+ process . exit ( 1 ) ;
155209}
156210
157211// start the server!
158212function main ( )
159213{
160- // open the database
161- prepareDatabase ( ) ;
214+ // open the database
215+ prepareDatabase ( ) ;
162216
163- // start the server listening
164- frontend . listen ( config . port , ( ) => console . log ( `Server running on port ${ config . port } !` ) ) ;
217+ // start the server listening
218+ frontend . listen ( config . port , ( ) => console . log ( `Server running on port ${ config . port } !` ) ) ;
165219}
166220
167221// go!
0 commit comments