Compare commits

...

25 Commits

Author SHA1 Message Date
Martin Donnelly
abb2145f0d Merge branch 'TRAINTIMES-1' into 'development'
TRAINTIMES-1 Websocket work

See merge request martind2000/traintimesPWA!15
2020-09-16 10:06:52 +00:00
Martin Donnelly
b2df620cc0 TRAINTIMES-1 Websocket work 2020-09-16 11:06:11 +01:00
Martin Donnelly
918a94090a Merge branch 'ttpwa-004' into 'development'
Forcing twitter.js to exit when the processor 'stops'.

See merge request martind2000/traintimesPWA!14
2020-08-21 08:03:15 +00:00
Martin Donnelly
04378b56ee Forcing twitter.js to exit when the processor 'stops'. 2020-08-21 09:02:43 +01:00
Martin Donnelly
e6695008ab removed db 2020-08-20 20:02:13 +01:00
Martin Donnelly
f872e0c5bb merged db? 2020-08-20 19:58:36 +01:00
Martin Donnelly
4feabbfdd3 Merge branch 'ttpwa-004' into 'development'
Fixes on the front end to handle twitter websocket a bit better

See merge request martind2000/traintimesPWA!13
2020-08-20 18:56:04 +00:00
Martin Donnelly
bfdc2ae28c Fixes on the front end to handle twitter websocket a bit better 2020-08-20 19:55:40 +01:00
Martin Donnelly
ac37a52bef Merge branch 'ttpwa-004' into 'development'
Fixes and tidying up the server side of the sockets

See merge request martind2000/traintimesPWA!12
2020-08-20 14:36:51 +00:00
Martin Donnelly
13b905e1f5 Fixes and tidying up the server side of the sockets 2020-08-20 15:34:55 +01:00
Martin Donnelly
a960fa2e07 Merge branch 'ttpwa-004' into 'development'
Fixes and tidying up the server side of the sockets

See merge request martind2000/traintimesPWA!11
2020-08-20 14:32:12 +00:00
Martin Donnelly
a8b3e27038 Fixes and tidying up the server side of the sockets 2020-08-20 15:31:43 +01:00
Martin Donnelly
e5be72a769 Merge branch 'ttpwa-004' into 'development'
Fixes and tidying up the server side of the sockets

See merge request martind2000/traintimesPWA!10
2020-08-20 14:08:47 +00:00
Martin Donnelly
204d995a4a Fixes and tidying up the server side of the sockets 2020-08-20 15:08:07 +01:00
Martin Donnelly
66ddf4c29b Merge branch 'ttpwa-004' into 'development'
Tracking down json retrieval issue

See merge request martind2000/traintimesPWA!9
2020-08-20 11:53:44 +00:00
Martin Donnelly
bbfebb31e1 Tracking down json retrieval issue
* Fix the json issue in store
2020-08-20 12:53:10 +01:00
Martin Donnelly
dddc49cf74 Merge branch 'ttpwa-004' into 'development'
Tracking down json retraval issue

See merge request martind2000/traintimesPWA!8
2020-08-20 11:42:46 +00:00
Martin Donnelly
f9a32557e3 Tracking down json retraval issue
* Fix to prevent websocket subscription requests happening before socket is fully connected
2020-08-20 12:42:18 +01:00
Martin Donnelly
3fdabc5322 Merge branch 'ttpwa-004' into 'development'
Tracking down json retraval issue

See merge request martind2000/traintimesPWA!7
2020-08-20 11:21:03 +00:00
Martin Donnelly
0bc893b68c Tracking down json retraval issue 2020-08-20 12:20:03 +01:00
Martin Donnelly
396086e3cd Merge branch 'ttpwa-004' into 'development'
Svelte app bump

See merge request martind2000/traintimesPWA!6
2020-08-20 11:04:06 +00:00
Martin Donnelly
acbb807d8a * New version of Svelte app which works with websockets for twitter 2020-08-20 12:01:21 +01:00
Martin Donnelly
669f2249bc Merge branch 'feature/websockets' into development
* feature/websockets:
  * Twitter now cleans db on restart
  wip
2020-08-19 11:27:03 +01:00
Martin Donnelly
da5d1384c5 * Twitter now cleans db on restart
* Server now handles websockets and sends tweets to websocket

* Added new ecosystem for pm2 to control server/twitter
2020-08-19 11:25:53 +01:00
Martin Donnelly
1e03d1697a wip 2020-08-16 20:05:28 +01:00
82 changed files with 33525 additions and 38 deletions

1
.gitignore vendored
View File

@ -151,3 +151,4 @@ fabric.properties
/src/es2016/bundle.js.map
/src/backbone/bundle.js.map
/db/twitter.db

Binary file not shown.

17
ecosystem.config.js Normal file
View File

@ -0,0 +1,17 @@
module.exports = {
'apps': [{
'name': 'Traintimes Server',
'script': './server.js',
'watch': ['./server.js', 'live/build'],
'env': {
'LOGGER_LEVEL': 'warn'
}
}, {
'name': 'Twitter Grabber',
'script': './twitter.js',
'watch': './twitter.js',
'watch_delay': 10000,
'cron_restart': '0 4 * * */3'
}]
};

0
live/bridger.js Normal file
View File

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -275,3 +275,48 @@
.fa-clockface-filled:before {
content: "\E9AA"
}
.fa-twitter:before {
content: "\EAE5"
}
.fa-cog:before {
content: "\EA9E"
}
.fa-cog-solid:before {
content: "\EA11"
}
.fa-foursquare:before {
content: "\EA0B"
}
/*full list*/
.fa-binoculars-solid:before {
content: "\E900"
}
.fa-binoculars:before {
content: "\E901"
}
.fa-check-circle-solid:before {
content: "\E902"
}
.fa-check-circle:before {
content: "\E903"
}

View File

@ -0,0 +1 @@
.bbm-wrapper{position:fixed;left:0;top:0;width:100%;height:100%;z-index:1;padding:50px 10px;overflow:auto}.bbm-wrapper,.bbm-wrapper *{box-sizing:border-box}.bbm-modal{border-radius:3px;margin:auto;width:auto;max-width:550px}.bbm-views{width:100%;box-sizing:border-box}

File diff suppressed because one or more lines are too long

1
live/css/common.css Normal file
View File

@ -0,0 +1 @@
body{background-color:#eee}.card{position:relative;background-color:#fff;min-height:48px;margin:8px;border-bottom-color:#666;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}.mui--text-display3,.mui--text-display4{font-family:Roboto Slab,Helvetica Neue,Helvetica,Arial}.temp0,.temp1,.temp2,.temp3,.temp4,.temp5{color:#50b5dd}.temp6{color:#4eb2ce}.temp7{color:#4cb0be}.temp8{color:#49adaf}.temp9{color:#48ab9f}.temp10{color:#46a88e}.temp11{color:#44a67d}.temp12{color:#42a46c}.temp13{color:#66ad5e}.temp14{color:#87be40}.temp15{color:#b3cc1a}.temp16{color:#d6d51c}.temp17{color:#f9ca03}.temp18{color:#f6b503}.temp19{color:#f4961a}.temp20{color:#ec6e05}.day{font-family:Roboto Slab,Helvetica Neue,Helvetica,Arial,sans-serif;text-transform:uppercase}.summary:first-letter{text-transform:capitalize}

1
live/css/mui.custom.css Normal file

File diff suppressed because one or more lines are too long

1
live/css/style.min.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
live/fonts/GothamSSm-Black.otf Executable file

Binary file not shown.

BIN
live/fonts/GothamSSm-Bold.otf Executable file

Binary file not shown.

BIN
live/fonts/GothamSSm-Book.otf Executable file

Binary file not shown.

BIN
live/fonts/GothamSSm-Light.otf Executable file

Binary file not shown.

BIN
live/fonts/GothamSSm-Medium.otf Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

32
live/fonts/fonts.css Normal file
View File

@ -0,0 +1,32 @@
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(Roboto-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Roboto Condensed';
font-style: normal;
font-weight: 400;
src: url(Roboto_Condensed-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
src: url(Roboto_Mono-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Roboto Slab';
font-style: normal;
font-weight: 400;
src: url(Roboto_Slab-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}

209
live/fonts/fujicons.css Normal file
View File

@ -0,0 +1,209 @@
@font-face {
font-family: 'Fujicons';
font-style: normal;
font-weight: 400;
src: url(fujicons.ttf) format('truetype');
unicode-range: U+0-10FFFF;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 Fujicons;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* makes the font 33% larger relative to the icon container */
.fa-lg {
font-size: 1.33333333em;
line-height: 0.75em;
vertical-align: -15%;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-fw {
width: 1.28571429em;
text-align: center;
}
.fa-ul {
padding-left: 0;
margin-left: 2.14285714em;
list-style-type: none;
}
.fa-ul > li {
position: relative;
}
.fa-li {
position: absolute;
left: -2.14285714em;
width: 2.14285714em;
top: 0.14285714em;
text-align: center;
}
.fa-li.fa-lg {
left: -1.85714286em;
}
.fa-border {
padding: .2em .25em .15em;
border: solid 0.08em #eeeeee;
border-radius: .1em;
}
.fa-pull-left {
float: left;
}
.fa-pull-right {
float: right;
}
.fa.fa-pull-left {
margin-right: .3em;
}
.fa.fa-pull-right {
margin-left: .3em;
}
/* Deprecated as of 4.4.0 */
.pull-right {
float: right;
}
.pull-left {
float: left;
}
.fa.pull-left {
margin-right: .3em;
}
.fa.pull-right {
margin-left: .3em;
}
.fa-spin {
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
.fa-pulse {
-webkit-animation: fa-spin 1s infinite steps(8);
animation: fa-spin 1s infinite steps(8);
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fa-rotate-90 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
-webkit-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
-webkit-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
-webkit-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
}
:root .fa-rotate-90,
:root .fa-rotate-180,
:root .fa-rotate-270,
:root .fa-flip-horizontal,
:root .fa-flip-vertical {
filter: none;
}
.fa-stack {
position: relative;
display: inline-block;
width: 2em;
height: 2em;
line-height: 2em;
vertical-align: middle;
}
.fa-stack-1x,
.fa-stack-2x {
position: absolute;
left: 0;
width: 100%;
text-align: center;
}
.fa-stack-1x {
line-height: inherit;
}
.fa-stack-2x {
font-size: 2em;
}
.fa-inverse {
color: #ffffff;
}
.fa-back:before {
content: "";
}
.fa-forward:before {
content: "";
}
.fa-globe:before {
content: "\EA12"
}
.fa-up:before {
content: "\E925"
}
.fa-down:before {
content: "\E922"
}
.fa-work:before {
content: "\E998"
}
.fa-home:before {
content: "\EA1E"
}
.fa-refresh:before {
content: "\EA88"
}

BIN
live/fonts/fujicons.ttf Executable file

Binary file not shown.

39
live/fonts/gotham.css Normal file
View File

@ -0,0 +1,39 @@
@font-face {
font-family: 'Gotham';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Book.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Light';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Light.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Medium';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Medium.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Bold';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Bold.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Black';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Black.otf) format('opentype');
unicode-range: U+0-10FFFF;
}

15886
live/js/bundle.js Normal file

File diff suppressed because one or more lines are too long

1
live/js/bundle.js.map Normal file

File diff suppressed because one or more lines are too long

1
live/js/vendor.js Normal file

File diff suppressed because one or more lines are too long

46
live/site.webmanifest Normal file
View File

@ -0,0 +1,46 @@
{
"name": "Train Times",
"short_name": "Train Times",
"icons": [
{
"src": "/img/Icon-36.png",
"sizes": "36x36",
"type": "image/png"
},
{
"src": "/img/Icon-48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "/img/Icon-72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/img/Icon-96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/img/Icon-144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/img/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/img/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"start_url": ".",
"imgdisplay": "standalone",
"display": "standalone"
}

6
notes.md Normal file
View File

@ -0,0 +1,6 @@
# notes
```
git flow feature finish websockets
```

0
old_live/bridger.js Normal file
View File

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/img/mstile-150x150.png"/>
<TileColor>#2b5797</TileColor>
</tile>
</msapplication>
</browserconfig>

File diff suppressed because one or more lines are too long

1
old_live/css/style.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

BIN
old_live/fonts/GothamSSm-Bold.otf Executable file

Binary file not shown.

BIN
old_live/fonts/GothamSSm-Book.otf Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

32
old_live/fonts/fonts.css Normal file
View File

@ -0,0 +1,32 @@
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(Roboto-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Roboto Condensed';
font-style: normal;
font-weight: 400;
src: url(Roboto_Condensed-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
src: url(Roboto_Mono-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Roboto Slab';
font-style: normal;
font-weight: 400;
src: url(Roboto_Slab-normal-400.woff) format('woff');
unicode-range: U+0-10FFFF;
}

209
old_live/fonts/fujicons.css Normal file
View File

@ -0,0 +1,209 @@
@font-face {
font-family: 'Fujicons';
font-style: normal;
font-weight: 400;
src: url(fujicons.ttf) format('truetype');
unicode-range: U+0-10FFFF;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 Fujicons;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* makes the font 33% larger relative to the icon container */
.fa-lg {
font-size: 1.33333333em;
line-height: 0.75em;
vertical-align: -15%;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-fw {
width: 1.28571429em;
text-align: center;
}
.fa-ul {
padding-left: 0;
margin-left: 2.14285714em;
list-style-type: none;
}
.fa-ul > li {
position: relative;
}
.fa-li {
position: absolute;
left: -2.14285714em;
width: 2.14285714em;
top: 0.14285714em;
text-align: center;
}
.fa-li.fa-lg {
left: -1.85714286em;
}
.fa-border {
padding: .2em .25em .15em;
border: solid 0.08em #eeeeee;
border-radius: .1em;
}
.fa-pull-left {
float: left;
}
.fa-pull-right {
float: right;
}
.fa.fa-pull-left {
margin-right: .3em;
}
.fa.fa-pull-right {
margin-left: .3em;
}
/* Deprecated as of 4.4.0 */
.pull-right {
float: right;
}
.pull-left {
float: left;
}
.fa.pull-left {
margin-right: .3em;
}
.fa.pull-right {
margin-left: .3em;
}
.fa-spin {
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
.fa-pulse {
-webkit-animation: fa-spin 1s infinite steps(8);
animation: fa-spin 1s infinite steps(8);
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fa-rotate-90 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
-webkit-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
-webkit-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
-webkit-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
}
:root .fa-rotate-90,
:root .fa-rotate-180,
:root .fa-rotate-270,
:root .fa-flip-horizontal,
:root .fa-flip-vertical {
filter: none;
}
.fa-stack {
position: relative;
display: inline-block;
width: 2em;
height: 2em;
line-height: 2em;
vertical-align: middle;
}
.fa-stack-1x,
.fa-stack-2x {
position: absolute;
left: 0;
width: 100%;
text-align: center;
}
.fa-stack-1x {
line-height: inherit;
}
.fa-stack-2x {
font-size: 2em;
}
.fa-inverse {
color: #ffffff;
}
.fa-back:before {
content: "";
}
.fa-forward:before {
content: "";
}
.fa-globe:before {
content: "\EA12"
}
.fa-up:before {
content: "\E925"
}
.fa-down:before {
content: "\E922"
}
.fa-work:before {
content: "\E998"
}
.fa-home:before {
content: "\EA1E"
}
.fa-refresh:before {
content: "\EA88"
}

BIN
old_live/fonts/fujicons.ttf Executable file

Binary file not shown.

39
old_live/fonts/gotham.css Normal file
View File

@ -0,0 +1,39 @@
@font-face {
font-family: 'Gotham';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Book.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Light';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Light.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Medium';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Medium.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Bold';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Bold.otf) format('opentype');
unicode-range: U+0-10FFFF;
}
@font-face {
font-family: 'Gotham Black';
font-style: normal;
font-weight: 400;
src: url(GothamSSm-Black.otf) format('opentype');
unicode-range: U+0-10FFFF;
}

BIN
old_live/img/Icon-144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
old_live/img/Icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
old_live/img/Icon-36.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
old_live/img/Icon-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
old_live/img/Icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
old_live/img/Icon-72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
old_live/img/Icon-96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
old_live/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,33 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="192.000000pt" height="192.000000pt" viewBox="0 0 192.000000 192.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,192.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M440 1789 c-80 -4 -104 -10 -149 -35 -63 -34 -117 -94 -145 -162 -19
-45 -20 -74 -20 -637 l0 -590 25 -56 c32 -67 91 -128 156 -160 l48 -23 605 -1
605 0 53 28 c69 35 118 86 151 156 l26 56 0 585 c-1 534 -2 590 -18 637 -33
94 -133 180 -231 199 -47 8 -969 11 -1106 3z m389 -79 c21 0 51 -44 51 -74 l0
-34 80 -1 c79 -1 80 -1 80 23 0 40 21 74 51 85 57 20 112 -21 112 -83 0 -17 5
-26 16 -26 68 0 143 -50 172 -115 17 -37 19 -74 19 -455 0 -265 -4 -429 -11
-454 -6 -23 -28 -55 -55 -81 l-44 -43 85 -89 c91 -94 101 -118 63 -153 -41
-38 -61 -28 -194 105 l-125 125 -168 0 -167 0 -128 -125 c-136 -134 -157 -145
-196 -103 -35 38 -26 60 65 155 l85 88 -35 30 c-19 16 -44 48 -55 70 -18 38
-19 65 -19 468 -1 404 1 431 19 467 32 63 105 110 171 110 11 0 16 8 14 23 -3
48 53 104 93 91 8 -2 17 -4 21 -4z"/>
<path d="M819 1532 c-48 -15 -65 -75 -31 -106 16 -14 43 -16 172 -17 169 0
190 7 190 62 0 25 -21 57 -38 60 -22 4 -282 4 -293 1z"/>
<path d="M735 1342 c-93 -5 -94 -6 -94 -192 0 -143 2 -160 19 -175 18 -16 48
-18 301 -18 l282 -1 18 23 c17 20 19 42 19 176 0 133 -2 154 -18 168 -15 14
-52 17 -242 19 -124 2 -252 2 -285 0z"/>
<path d="M685 741 c-35 -22 -50 -67 -35 -107 12 -32 55 -57 93 -56 44 1 88 50
81 89 -9 52 -15 63 -43 78 -34 17 -63 16 -96 -4z"/>
<path d="M1138 745 c-49 -27 -58 -97 -18 -137 55 -54 139 -31 154 43 7 38 -9
71 -44 92 -34 21 -56 21 -92 2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

75
old_live/index.html Normal file
View File

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Train Times</title>
<link href="fonts/fonts.css" rel="stylesheet">
<link href="fonts/gotham.css" rel="stylesheet">
<link href="fonts/fujicons.css" rel="stylesheet" type="text/css"/>
<link href="css/mui.custom.css" rel="stylesheet" type="text/css"/>
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<link rel="mask-icon" href="/img/safari-pinned-tab.svg" color="#5bbad5">
<meta name="apple-mobile-web-app-title" content="Train Times">
<meta name="application-name" content="Train Times">
<meta name="theme-color" content="#ffffff">
<link href="css/style.min.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="_hero" style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
"></div>
<div class="appPanel" data-id="main">
<header id="header">
<div class="mui-appbar mui--appbar-line-height mui--z2">
<div class='mui-col-xs-8 mui-col-md-8 mui--appbar-height titleBar'>Train Times</div>
<div class='mui-col-xs-4 mui-col-md-4 mui--appbar-height'></div>
</div>
</header>
<div class="mui--appbar-height"></div>
<div class="mui-container">
<div class="app"></div>
<div id="trains" ></div>
<!--<div id='trainResults' class="mui&#45;&#45;hide"></div>-->
</div>
</div>
<div id="snackbar">⚡ Offline, waiting to reconnect...</div>
<script type="text/template" id="modal-template">
<!--<div class="bbm-modal__topbar">
<h3 class="bbm-modal__title">Backbone.Modal</h3>
</div>-->
<div class="bbm-modal__section" id="modalContent">
</div>
<div class="bbm-modal__bottombar">
<a href="#" class="bbm-button">close</a>
</div>
</script>
<!--<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>-->
<script src="js/vendor.js" async></script>
<script src="js/bundle.js" async></script>
</body>
</html>

15837
old_live/js/bundle.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
old_live/js/vendor.js Normal file

File diff suppressed because one or more lines are too long

46
old_live/manifest.json Normal file
View File

@ -0,0 +1,46 @@
{
"name": "Train Times",
"short_name": "Train Times",
"icons": [
{
"src": "/img/Icon-36.png",
"sizes": "36x36",
"type": "image/png"
},
{
"src": "/img/Icon-48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "/img/Icon-72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/img/Icon-96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/img/Icon-144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/img/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/img/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"start_url": ".",
"imgdisplay": "standalone",
"display": "standalone"
}

113
old_live/service-worker.js Normal file
View File

@ -0,0 +1,113 @@
// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const CACHE_VERSION = 7;
const dataCacheName = `traintimesData-v${CACHE_VERSION}`;
const cacheName = `traintimePWA-final-${CACHE_VERSION}`;
const filesToCache = [
'/',
'/index.html',
'/service-worker.js',
'/manifest.json',
'/browserconfig.xml',
'/css/style.min.css',
'/css/mui.custom.css',
'/fonts/fonts.css',
'/fonts/gotham.css',
'/fonts/Roboto-normal-400.woff',
'/fonts/Roboto_Mono-normal-400.woff',
'/js/bundle.js',
'/js/vendor.js',
'/img/Icon-36.png',
'/img/Icon-48.png',
'/img/Icon-72.png',
'/img/Icon-96.png',
'/img/Icon-144.png',
'/img/Icon-192.png',
'/img/Icon-512.png'
];
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== cacheName && key !== dataCacheName) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
/*
* Fixes a corner case in which the app wasn't returning the latest data.
* You can reproduce the corner case by commenting out the line below and
* then doing the following steps: 1) load app for first time so that the
* initial New York City data is shown 2) press the refresh button on the
* app 3) go offline 4) reload the app. You expect to see the newer NYC
* data, but you actually see the initial data. This happens because the
* service worker is not yet activated. The code below essentially lets
* you activate the service worker faster.
*/
return self.clients.claim();
});
self.addEventListener('fetch', function(e) {
console.warn('[Service Worker] Fetch', e.request.url);
const dataUrl = '/getnexttraintimes?';
if (e.request.url.indexOf(dataUrl) > -1) {
console.log('!');
/*
* When the request URL contains dataUrl, the app is asking for fresh
* weather data. In this case, the service worker always goes to the
* network and then caches the response. This is called the "Cache then
* network" strategy:
* https://jakearchibald.com/2014/offline-cookbook/#cache-then-network
*/
e.respondWith(
caches.open(dataCacheName).then(function(cache) {
return fetch(e.request).then(function(response) {
cache.put(e.request.url, response.clone());
return response;
});
})
);
}
else
/*
* The app is asking for app shell files. In this scenario the app uses the
* "Cache, falling back to the network" offline strategy:
* https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network
*/
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});

117
package-lock.json generated
View File

@ -1195,6 +1195,14 @@
"integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
"dev": true
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bl": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz",
@ -1915,6 +1923,11 @@
"integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
"dev": true
},
"cuid": {
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/cuid/-/cuid-2.1.8.tgz",
"integrity": "sha512-xiEMER6E7TlTPnDxrM4eRiC6TRgjNX9xzEZ5U/Se2YJKr7Mq4pJn/2XEHjl3STcSh96GmkHPcBXLES8M29wyyg=="
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@ -2162,6 +2175,11 @@
"integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=",
"optional": true
},
"duplexer": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
},
"duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@ -2570,6 +2588,20 @@
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"event-stream": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz",
"integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==",
"requires": {
"duplexer": "^0.1.1",
"from": "^0.1.7",
"map-stream": "0.0.7",
"pause-stream": "^0.0.11",
"split": "^1.0.1",
"stream-combiner": "^0.2.2",
"through": "^2.3.8"
}
},
"events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
@ -2740,8 +2772,7 @@
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"filename-regex": {
"version": "2.0.1",
@ -2926,6 +2957,11 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"from": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
"integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
},
"fs-minipass": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
@ -5114,8 +5150,7 @@
"lodash.assign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
"dev": true
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
},
"lodash.create": {
"version": "3.1.1",
@ -5437,6 +5472,11 @@
"pify": "^3.0.0"
}
},
"map-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
"integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg="
},
"md5.js": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
@ -5526,6 +5566,11 @@
"integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
"dev": true
},
"mingo": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/mingo/-/mingo-1.3.3.tgz",
"integrity": "sha1-aSLE0Ufvx3GgFCWixMj3eER4xUY="
},
"minibus": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/minibus/-/minibus-3.1.0.tgz",
@ -5793,6 +5838,14 @@
}
}
},
"node-crc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/node-crc/-/node-crc-1.3.0.tgz",
"integrity": "sha512-XSs9gZhZKdiwpJDLSoRQsnn8N9q/KH4bc0ayO6+qnHbtb1YfIrdKfjbOQFCwup4q/D2sNxhbupvrZ3rWmzAk4A==",
"requires": {
"bindings": "^1.3.0"
}
},
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
@ -6388,6 +6441,14 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"pause-stream": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
"integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
"requires": {
"through": "~2.3"
}
},
"pbkdf2": {
"version": "3.0.14",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
@ -7038,6 +7099,32 @@
"integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==",
"dev": true
},
"save": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/save/-/save-2.4.0.tgz",
"integrity": "sha512-wd5L2uVnsKYkIUaK6i8Ie66IOHaI328gMF0MPuTJtYOjXgUolC33LSIk7Qr8WVA55QHaGwfiVS8a7EFIeGOR3w==",
"requires": {
"async": "^2.6.2",
"event-stream": "^4.0.1",
"lodash.assign": "^4.2.0",
"mingo": "1"
},
"dependencies": {
"async": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"requires": {
"lodash": "^4.17.14"
}
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
}
}
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@ -7348,6 +7435,14 @@
"source-map": "^0.5.6"
}
},
"split": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
"requires": {
"through": "2"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -7400,6 +7495,15 @@
"readable-stream": "^2.0.2"
}
},
"stream-combiner": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
"integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=",
"requires": {
"duplexer": "~0.1.1",
"through": "~2.3.4"
}
},
"stream-combiner2": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
@ -8775,6 +8879,11 @@
"mkdirp": "^0.5.1"
}
},
"ws": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
},
"xregexp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz",

View File

@ -4,7 +4,8 @@
"description": "Train Times Progressive Web App",
"main": "app.js",
"scripts": {
"start:twitter": "node twitter.js",
"start:server": "node server.js"
},
"author": "",
"license": "ISC",
@ -15,6 +16,7 @@
"browserify": "^14.5.0",
"compressjs": "^1.0.3",
"cors": "^2.8.4",
"cuid": "^2.1.8",
"dotenv": "^8.2.0",
"es6-promise": "^4.1.1",
"express": "^4.16.2",
@ -25,9 +27,12 @@
"lz77": "^1.1.0",
"minibus": "^3.1.0",
"muicss": "^0.9.33",
"node-crc": "^1.3.0",
"save": "^2.4.0",
"sqlite3": "^4.2.0",
"twitter-lite": "^0.11.0",
"underscore": "^1.8.3"
"underscore": "^1.8.3",
"ws": "^7.3.1"
},
"devDependencies": {
"babel-cli": "^6.26.0",

View File

@ -1,3 +1,4 @@
const http = require('http');
const express = require('express');
const cors = require('cors');
@ -7,7 +8,14 @@ const logger = require('log4js').getLogger('Server');
const train = require('./server/lib/train');
const twitter = require('./server/lib/twitter');
logger.level = 'debug';
const WebSocket = require('ws');
const SocketHandler = require('./server/lib/wshandlerv3');
const Events = require('events');
const busEmitter = new Events.EventEmitter();
logger.level = process.env.LOGGER_LEVEL || 'debug';
const app = express();
const port = process.env.PORT || 8100;
@ -34,9 +42,29 @@ process.on('uncaughtException', err => {
logger.error(err);
});
app.listen(port, (err) => {
/* app.listen(port, (err) => {
if (err)
return logger.error('Server error:', err);
logger.info(`TrainTime Server is listening on ${port}`);
});*/
const server = http.createServer(app);
try {
const wss = new WebSocket.Server({ server });
const webSocket = new SocketHandler(busEmitter, wss);
twitter.updates(busEmitter);
}
catch (e) {
logger.error(e);
}
server.listen(port, (err) => {
if (err)
return logger.error('Server error:', err);
logger.info(`New Traintime server listening on ${ server.address().port}`);
});

View File

@ -1,7 +1,9 @@
const logger = require('log4js').getLogger('DBManager');
const db = require('./connect');
const fecha = require('fecha');
logger.level = process.env.LOGGER_LEVEL || 'debug';
// exports.create = (req, res) => {
function prepareData(_obj) {
@ -22,8 +24,36 @@ function prepareData(_obj) {
exports.prepareData = prepareData;
exports.vacuum = () => {
logger.info('>> vacuum:');
return new Promise((resolve, reject) => {
db.run('VACUUM', function(err) {
if (err)
reject(err);
resolve({ 'msg':'Vacuum', 'changes': this.changes });
});
});
};
exports.deleteUpTo = (ms) => {
logger.info('>> deleteUpTo:', ms);
const sql = 'delete from tweets where createdAt < ?';
return new Promise((resolve, reject) => {
db.run(sql, ms, function(err) {
if (err)
reject(err);
resolve({ 'msg':'Rows deleted', 'changes': this.changes });
});
});
};
exports.getAll = (list) => {
console.log('>> getAll:', list);
logger.info('>> getAll:', list);
const outgoing = [];
// const sql = 'SELECT * FROM tweets order by _id desc limit 20';
@ -43,6 +73,29 @@ exports.getAll = (list) => {
});
};
exports.getLatestTweets = (ms) => {
logger.info('>> getAll:', ms);
const outgoing = [];
// const sql = 'SELECT * FROM tweets order by _id desc limit 20';
const ts = (new Date().getTime() - ms) ;
const sql = 'SELECT * FROM tweets where ts>=? order by ts asc';
return new Promise((resolve, reject) => {
db.all(sql, [ts], (err, rows) => {
if (err)
reject(err);
rows.forEach((row) => {
outgoing.push(row);
});
resolve(outgoing) ;
});
});
};
exports.getTopOne = (hash) => {
const sql = 'SELECT * FROM tweets order by _id desc limit 1';
@ -56,7 +109,6 @@ exports.getTopOne = (hash) => {
});
};
exports.getOne = (hash) => {
const sql = 'SELECT * FROM menu WHERE hash = ?';
@ -154,7 +206,7 @@ exports.getRandom = (timestamp) => {
exports.updateTimestamps = (newTimestamp, items) => {
const sqlTimestamp = ~~(newTimestamp / 1000);
console.log('>> items', items);
logger.info('>> items', items);
const sql = 'UPDATE menu SET lastused = $lastused WHERE _id = $in';
@ -163,7 +215,7 @@ exports.updateTimestamps = (newTimestamp, items) => {
const stmt = db.prepare(sql);
items.forEach((item) => {
console.log(item);
logger.info(item);
const newData = { '$lastused':sqlTimestamp, '$in':item };
stmt.run(newData);

102
server/lib/pubsub.js Normal file
View File

@ -0,0 +1,102 @@
const logger = require('log4js').getLogger('pubsub');
logger.level = process.env.LOGGER_LEVEL || 'debug';
class PubSubManager {
constructor() {
this.channels = {
'twitter': {
},
'weather': {
'message': '',
'subscribers': []
},
'sports': {
'message': '',
'subscribers': []
}
};
this.brokerId = setInterval(() => {
this.broker();
}, 1000);
/* this.updater = setInterval(() => {
this.doUpdater();
}, 60000);*/
}
subscribe(subscriber, channel) {
const channelSplit = channel.split('-');
if (channelSplit[0] === 't') {
if (!this.channels.twitter.hasOwnProperty(channel))
this.channels.twitter[channel] = {
'message': null,
'subscribers': []
};
logger.info(`subscribing to ${channel}`);
this.channels.twitter[channel].subscribers.push(subscriber);
}
}
unsubscribe(id) {
logger.info('Forcing unsub for', id);
for (const channel in this.channels.twitter)
if (this.channels.twitter.hasOwnProperty(channel)) {
const channelObj = this.channels.twitter[channel];
channelObj.subscribers = channelObj.subscribers.filter(item => item.cuid !== id);
}
}
removeBroker() {
clearInterval(this.brokerId);
}
publish(publisher, channel, message) {
this.channels[channel].message = message;
}
publishTwitter( channel, message) {
// logger.debug('Publish:', channel, message);
if (!this.channels.twitter.hasOwnProperty(channel))
this.channels.twitter[channel] = {
'message': null,
'subscribers': []
};
this.channels.twitter[channel].message = message;
}
doUpdater() {
for (const channel in this.channels.twitter)
// logger.debug(channel);
if (this.channels.twitter.hasOwnProperty(channel)) {
const channelObj = this.channels.twitter[channel];
logger.info(`Subscribers: ${channelObj.subscribers.length} in ${channel}`);
// logger.info(channelObj.subscribers);
}
}
broker() {
// logger.debug('Broker...');
for (const channel in this.channels.twitter)
// logger.debug(channel);
if (this.channels.twitter.hasOwnProperty(channel)) {
const channelObj = this.channels.twitter[channel];
if (channelObj.message) {
logger.info(`found message: ${channelObj.message} in ${channel}`);
channelObj.subscribers.forEach(subscriber => {
subscriber.send(JSON.stringify({
'message': channelObj.message
}));
});
channelObj.message = '';
}
}
}
}
module.exports = PubSubManager;

View File

@ -2,6 +2,7 @@
const request = require('request');
const http = require('http');
const cheerio = require('cheerio');
const crc = require('node-crc');
// const STRING = require('string');
const logger = require('log4js').getLogger('train');
const trainCache = {
@ -9,7 +10,7 @@ const trainCache = {
'data': {}
};
logger.level = 'info';
logger.level = process.env.LOGGER_LEVEL || 'debug';
function getTrainTimes(req, res) {
// console.log(req);
@ -20,6 +21,15 @@ function getTrainTimes(req, res) {
// logger.debug(`https://huxley.apphb.com${url}`);
Query(function (a, b) {
if (a.hasOwnProperty('nrccMessages') && a.nrccMessages !== null)
a.nrccMessages = a.nrccMessages.map((item) => {
const crcid = crc.crc64(Buffer.from(item.value, 'utf8')).toString('hex');
item.id = `nrcc-${crcid}`;
return item;
});
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(a));
@ -197,12 +207,12 @@ function Query(callback, r, host, path) {
callback(JSON.parse(data), r);
});
response.on('error', function (e) {
console.error(e);
logger.error(e);
});
}).end();
}
catch (e) {
console.log(e);
logger.debug(e);
}
}

View File

@ -5,8 +5,44 @@
* Time: 16:19
*/
const logger = require('log4js').getLogger('Twitter');
const dbmanager = require('../db/dbmanager');
const rawTwitterList = require('./twitterList.json');
let twitterList = [];
let intervalID = 0;
let eventEmitter;
logger.level = process.env.LOGGER_LEVEL || 'debug';
function doTweetUpdates() {
logger.info('doTweetUpdates');
dbmanager.getLatestTweets(10000)
.then((data) => {
data.forEach((item) => {
if(twitterList.indexOf(item.userID) !== -1)
eventEmitter.emit('sendTweet', `t-${item.userIDStr}`, item);
});
})
.catch((err) => {
logger.error(err.message);
});
}
function buildList() {
twitterList = rawTwitterList.map((item) => {
return item.id;
});
logger.debug(twitterList);
}
function startTweetUpdates() {
logger.warn('StartTweetUpdates');
intervalID = setInterval(() => {
doTweetUpdates();
}, 10000);
}
exports.top = (req, res) => {
dbmanager.getTopOne()
@ -32,3 +68,13 @@ exports.all = (req, res) => {
});
});
};
exports.updates = (newEmitter) => {
logger.warn('Setting events');
eventEmitter = newEmitter;
buildList();
setTimeout(() => {
startTweetUpdates();
}, 30000);
};

262
server/lib/twitterList.json Normal file
View File

@ -0,0 +1,262 @@
[
{
"follow": false,
"name": "nationalrailenq",
"id": 33546465
},
{
"follow": false,
"name": "networkrail",
"id": 365344176
},
{
"follow": false,
"name": "NetworkRailSCOT",
"id": 402687948
},
{
"follow": false,
"name": "AvantiWestCoast",
"id": 1143560758476906497
},
{
"follow": false,
"name": "CalSleeper",
"id": 2870293725
},
{
"follow": false,
"name": "CrossCountryUK",
"id": 153368708
},
{
"follow": false,
"name": "Eurostar",
"id": 98412169
},
{
"follow": false,
"name": "EurostarUK",
"id": 59742254
},
{
"follow": false,
"name": "GatwickExpress",
"id": 163816182
},
{
"follow": false,
"name": "GlasgowSubway",
"id": 224607925
},
{
"follow": false,
"name": "GWRHelp",
"id": 15589815
},
{
"follow": false,
"name": "HeathrowExpress",
"id": 20240678
},
{
"follow": false,
"name": "LNER",
"id": 313306238
},
{
"follow": false,
"name": "LNRailway",
"id": 910487328627535872
},
{
"follow": false,
"name": "northernassist",
"id": 194512268
},
{
"follow": false,
"name": "ScotRail",
"id": 61569136
},
{
"follow": false,
"name": "Stansted_Exp",
"id": 257511611
},
{
"follow": false,
"name": "TfL",
"id": 47319664
},
{
"follow": false,
"name": "WestMidRailway",
"id": 915554470175657984
},
{
"follow": false,
"name": "NetworkRailBHM",
"id": 583910976
},
{
"follow": false,
"name": "NetworkRailEDB",
"id": 586614081
},
{
"follow": false,
"name": "NetworkRailEUS",
"id": 581807264
},
{
"follow": false,
"name": "NetworkRailGLC",
"id": 421061171
},
{
"follow": false,
"name": "NetworkRailKGX",
"id": 459192871
},
{
"follow": false,
"name": "NetworkRailLST",
"id": 581826097
},
{
"follow": false,
"name": "NetworkRailMAN",
"id": 583895871
},
{
"follow": false,
"name": "NetworkRailVIC",
"id": 587354752
},
{
"follow": false,
"name": "BTP",
"id": 266094415
},
{
"follow": false,
"name": "BTPAvonSomerset",
"id": 738664125132345344
},
{
"follow": false,
"name": "BTPBhm",
"id": 952003488
},
{
"follow": false,
"name": "BTPBlackCountry",
"id": 767698362866999297
},
{
"follow": false,
"name": "BTPCambs",
"id": 2574726074
},
{
"follow": false,
"name": "BTPCardiff_NWP",
"id": 951714852
},
{
"follow": false,
"name": "BTPEAnglia",
"id": 4479942923
},
{
"follow": false,
"name": "BTPEssex",
"id": 2949032015
},
{
"follow": false,
"name": "BTPGtrMcr",
"id": 1670204977
},
{
"follow": false,
"name": "BTPLeics",
"id": 761147194598711296
},
{
"follow": false,
"name": "BTPLiverpoolSt",
"id": 951912242
},
{
"follow": false,
"name": "BTPLondon",
"id": 957226980
},
{
"follow": false,
"name": "BTPLondonBridge",
"id": 3346645594
},
{
"follow": false,
"name": "BTPMersey",
"id": 951748434
},
{
"follow": false,
"name": "BTPNorthScot",
"id": 2238888007
},
{
"follow": false,
"name": "BTPNorthWales",
"id": 951487338
},
{
"follow": false,
"name": "BTPOxon",
"id": 741228701791178753
},
{
"follow": false,
"name": "BTPPontypridd",
"id": 1672678292
},
{
"follow": false,
"name": "BTPScotland",
"id": 957256160
},
{
"follow": false,
"name": "BTPSouthYorks",
"id": 3384315676
},
{
"follow": false,
"name": "BTPTeesValley",
"id": 802182849872936962
},
{
"follow": false,
"name": "BTPUnderground",
"id": 986236195049897985
},
{
"follow": false,
"name": "BTPWales",
"id": 1430734374
},
{
"follow": false,
"name": "BTPWaterloo",
"id": 951997044
},
{
"follow": false,
"name": "BTPWestScot",
"id": 951757261
}
]

50
server/lib/wshandlerv2.js Normal file
View File

@ -0,0 +1,50 @@
/**
*
* User: Martin Donnelly
* Date: 2016-09-07
* Time: 15:33
*
*/
const url = require('url');
const logger = require('log4js').getLogger();
module.exports = function(events, wsServer) {
'use strict';
logger.debug('>> new WS', wsServer);
wsServer.on('connection', function connection(ws) {
// console.log('>> WS:', ws);
// const location = url.parse(ws.upgradeReq.url, true);
logger.info('Creating event for this connection');
logger.info(`${new Date() } Connection accepted.`);
const sendSocketHandler = (obj) => {
logger.debug('sendSocketHandler', obj);
try {
ws.send(JSON.stringify(obj));
}
catch (err) {
logger.error(err);
logger.warn('Offending object: ', obj);
}
};
events.on('sendSocket', sendSocketHandler);
ws.on('message', function(message) {
console.log('received:', message);
if (message === 'update')
events.emit('update');
});
ws.on('close', function(reasonCode, description) {
logger.info(`${new Date() } Peer ${ connection.remoteAddress } disconnected.`);
events.removeListener('sendSocket', sendSocketHandler);
});
});
return module;
};

78
server/lib/wshandlerv3.js Normal file
View File

@ -0,0 +1,78 @@
/**
*
* User: Martin Donnelly
* Date: 2016-09-07
* Time: 15:33
*
*/
// from
// https://medium.com/unprogrammer/implementing-publisher-subscriber-pattern-using-javascript-nodejs-and-websockets-82036da7e174
const url = require('url');
const cuid = require('cuid');
const PubSubManager = require('./pubsub');
const logger = require('log4js').getLogger('wshandlerv3');
logger.level = process.env.LOGGER_LEVEL || 'debug';
const pubSubManager = new PubSubManager();
function noop() {}
function heartbeat() {
this.isAlive = true;
}
module.exports = function(events, wsServer) {
'use strict';
logger.debug('>> new WS', wsServer);
wsServer.on('connection', (ws, req) => {
ws.cuid = cuid();
logger.debug(`Connection request for ${ws.cuid}`);
ws.isAlive = true;
ws.on('pong', heartbeat);
ws.on('message', (data) => {
logger.debug(`data: ${ data}`, this);
const json = JSON.parse(data);
const request = json.request;
const message = json.message;
const channel = json.channel;
switch (request) {
case 'PUBLISH':
pubSubManager.publish(ws, channel, message);
break;
case 'SUBSCRIBE':
pubSubManager.subscribe(ws, channel);
break;
}
});
ws.on('close', () => {
logger.debug('Stopping client connection.', ws.cuid);
pubSubManager.unsubscribe(ws.cuid);
});
});
const interval = setInterval(function ping() {
wsServer.clients.forEach(function each(ws) {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
ws.ping(noop);
});
}, 30000);
const sendTweetHandler = (id, obj) => {
pubSubManager.publishTwitter(id, obj);
};
events.on('sendTweet', sendTweetHandler);
return module;
};

BIN
src/img/photothumb.db Normal file

Binary file not shown.

View File

@ -40,6 +40,7 @@ const accounts = [
{'name':'ScotRail', 'id':61569136},
{'name':'Stansted_Exp', 'id':257511611},
{'name':'TfL', 'id':47319664},
{'name':'WestMidRailway', 'id':915554470175657984},
{'name':'NetworkRailBHM', 'id':583910976},
{'name':'NetworkRailEDB', 'id':586614081},
@ -49,11 +50,37 @@ const accounts = [
{'name':'NetworkRailLST', 'id':581826097},
{'name':'NetworkRailMAN', 'id':583895871},
{'name':'NetworkRailVIC', 'id':587354752},
{'name':'BTP', 'id':266094415},
{'name':'BTPAvonSomerset', 'id':738664125132345344},
{'name':'BTPBhm', 'id':952003488},
{'name':'BTPBlackCountry', 'id':767698362866999297},
{'name':'BTPCambs', 'id':2574726074},
{'name':'BTPCardiff_NWP', 'id':951714852},
{'name':'BTPEAnglia', 'id':4479942923},
{'name':'BTPEssex', 'id':2949032015},
{'name':'BTPGtrMcr', 'id':1670204977},
{'name':'BTPLeics', 'id':761147194598711296},
{'name':'BTPLiverpoolSt', 'id':951912242},
{'name':'BTPLondon', 'id':957226980},
{'name':'BTPLondonBridge', 'id':3346645594},
{'name':'BTPMersey', 'id':951748434},
{'name':'BTPNorthScot', 'id':2238888007},
{'name':'BTPNorthWales', 'id':951487338},
{'name':'BTPOxon', 'id':741228701791178753},
{'name':'BTPPontypridd', 'id':1672678292},
{'name':'BTPScotland', 'id':957256160},
{'name':'BTPSouthYorks', 'id':3384315676},
{'name':'BTPTeesValley', 'id':802182849872936962},
{'name':'BTPUnderground', 'id':986236195049897985},
{'name':'BTPWales', 'id':1430734374},
{'name':'BTPWaterloo', 'id':951997044},
{'name':'BTPWestScot', 'id':951757261}
];
// {'name':'', 'id':},
(async function(){
/* const response = await user.getBearerToken();
@ -61,6 +88,29 @@ const accounts = [
bearer_token: response.access_token
});*/
const cleanDB = async function(){
const aDay = 86400000;
const now = new Date().getTime() ;
const oldDate = now - (15 * aDay);
console.log('Clean up to:', oldDate );
await dbmanager.deleteUpTo(oldDate).then((v) => {
console.log(v);
}).catch((err) => {
console.error(err);
});
await dbmanager.vacuum().then((v) => {
console.log(v);
}).catch((err) => {
console.error(err);
});
};
const validAccounts = accounts.map(item => {
return item.id;
})
@ -72,6 +122,8 @@ const accounts = [
console.log('Starting:', parameters);
await cleanDB();
const stream = client.stream("statuses/filter", parameters)
.on("start", response => console.log('Started!'))
.on("data", tweet => {
@ -84,6 +136,10 @@ const accounts = [
})
.on("ping", () => console.log('>> ping'))
.on("error", error => console.error(error))
.on("end", response => console.log('Stopped!'));
.on("end", response => {
console.error('Stopped!');
console.log(response);
process.exit(1);
});
})();

1
version.txt Normal file
View File

@ -0,0 +1 @@
2.1.0