Twitter enabled web page slideshow

This flow is based almost entirely on https://flows.nodered.org/flow/8666510f94ad422e4765

It adds a Twitter user input (@archillect) extracts the https url of the posted media and feed said url to the websocket, so it can be displayed by the webpage available at 'http://{your-server-ip:1880/slideshow'

The image gets somewhat resized to the dimension of the browser window. It's not working 100% of the time i.e. with 16:10 aspect monitors the images get stretched too much, It's far from perfect, but it's a start. In the page template there's some javascript added so you can go fullscreen (but that gets resetted when the image changes) see: http://blogs.sitepointstatic.com/examples/tech/full-screen/index.html

It works quite well if you cast a tab of your browser to a chromecast, or if you have a spare tablet you can basically have a Twitter powered photo display.

[
    {
        "id": "affb0fda.9189c",
        "type": "twitter in",
        "z": "fb5b6e33.9bc11",
        "twitter": "",
        "tags": "@archillect",
        "user": "user",
        "name": "",
        "topic": "tweets",
        "x": 170,
        "y": 60,
        "wires": [
            [
                "2ee36506.9e365a",
                "e27ad042.65f95"
            ]
        ]
    },
    {
        "id": "e27ad042.65f95",
        "type": "change",
        "z": "fb5b6e33.9bc11",
        "name": "get tweet object",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "tweet",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 160,
        "y": 140,
        "wires": [
            [
                "62c28189.4ce19"
            ]
        ]
    },
    {
        "id": "62c28189.4ce19",
        "type": "change",
        "z": "fb5b6e33.9bc11",
        "name": "get media https url",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.entities.media[0].media_url_https",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 390,
        "y": 140,
        "wires": [
            [
                "b7450e85.a8207",
                "fc94d254.85dd1"
            ]
        ]
    },
    {
        "id": "fc94d254.85dd1",
        "type": "websocket out",
        "z": "fb5b6e33.9bc11",
        "name": "",
        "server": "bc725200.1dc2d",
        "client": "",
        "x": 550,
        "y": 260,
        "wires": []
    },
    {
        "id": "8905b6ac.848648",
        "type": "http in",
        "z": "fb5b6e33.9bc11",
        "name": "",
        "url": "/slideshow",
        "method": "get",
        "swaggerDoc": "",
        "x": 140,
        "y": 200,
        "wires": [
            [
                "6864b831.fe7818"
            ]
        ]
    },
    {
        "id": "6864b831.fe7818",
        "type": "template",
        "z": "fb5b6e33.9bc11",
        "name": "HTML Slideshow",
        "field": "payload",
        "fieldType": "msg",
        "format": "html",
        "syntax": "mustache",
        "template": "<!DOCTYPE HTML>\n<html>\n    <head>\n    <style>\n*\n{\n\tpadding: 0;\n\tmargin: 0;\n}\n\nhtml, body\n{\n\tfont-family: \"Segoe UI\", arial, helvetica, freesans, sans-serif;\n\tcolor: #333;\n\tbackground-color: #000;\n\toverflow-y: auto;\n\toverflow-x: auto;\n}\n\nbody\n{\n\tmargin: 0 auto;\n\tmax-height: 100%;\n    max-width: 100%;\n}\n\np\n{\n\tmargin: 0 0 1em 0;\n}\n\nsection\n{\n\tdisplay: block;\n\tfloat: center;\n\tpadding: 0;\n\tmargin: 0 auto;\n\tborder: 0 none;\n\tcursor: pointer;\n\tmax-height: 100%;\n    max-width: 100%;\n}\n\n\nsection img\n{\n\twidth: 100%;\n\theight: 100%;\n}\n\n\nsection p\n{\n\tfont-weight: bold;\n\ttext-align: center;\n\tmargin: 0;\n}\n\nsection:-webkit-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n\tbackground-color: #f00;\n}\n\nsection:-moz-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n\nsection:-ms-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n\nsection:-o-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n\nsection:full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n</style>\n    <title>Simple Live Display</title>\n    <script src=\"https://code.jquery.com/jquery-latest.js\"></script>\n    <script type=\"text/javascript\">\n        var ws;\n        var wsUri = \"ws:\";\n        var loc = window.location;\n        console.log(loc);\n        if (loc.protocol === \"https:\") { wsUri = \"wss:\"; }\n        // This needs to point to the web socket in the Node-RED flow\n        // ... in this case it's ws/simple\n        wsUri += \"//\" + loc.host + loc.pathname.replace(\"slideshow\",\"ws/slideshow\");\n\n    function wsConnect() {\n            console.log(\"connect\",wsUri);\n            ws = new WebSocket(wsUri);\n            //var line = \"\";    // either uncomment this for a building list of messages\n            ws.onmessage = function(msg) {\n                var line = \"\";  // or uncomment this to overwrite the existing message\n                // parse the incoming message as a JSON object\n                var data = msg.data;\n                //console.log(data);\n                // build the output from the topic and payload parts of the object\n                // line += \"<p>\"+data+\"</p>\";\n                line += '<section id=\"fullscreen\" onclick=\"gofull();\"><img onload=\"fit_to_screen();\" src=\"' + data + '\"/></section>'\n                // replace the messages div with the new \"line\"\n                document.getElementById('messages').innerHTML = line;\n                //ws.send(JSON.stringify({data:data}));\n                 set_body_height();\n            }\n            ws.onopen = function() {\n                // update the status div with the connection status\n                document.getElementById('status').innerHTML = \"connected\";\n                //ws.send(\"Open for data\");\n                console.log(\"connected\");\n            }\n            ws.onclose = function() {\n                // update the status div with the connection status\n                document.getElementById('status').innerHTML = \"not connected\";\n                // in case of lost connection tries to reconnect every 3 secs\n                setTimeout(wsConnect,3000);\n            }\n        }\n  \n    function set_body_height() { // set body height = window height\n        $('body').height($(window).height());\n        $('body').width($(window).width());\n        fit_to_screen();\n    }\n    $(document).ready(function() {\n        $(window).bind('resize', set_body_height);\n        set_body_height();\n    });\n    \n    function fit_to_screen() {\n    img.removeAttribute(\"style\");\n    // var winX = window.innerWidth + \"px\";\n    var winX = $(window).width();\n    // var winY = window.innerHeight + \"px\";\n    var winY = $(window).height();\n    var vbar = false;\n    if (document.body.scrollHeight > document.body.clientHeight) // vertical scrollbar\n    {\n            img.style.height = winY;\n            vbar = true;\n    }\n    if (document.body.scrollWidth > document.body.clientWidth) // horizontal scrollbar\n    {\n            if (vbar) // both scrollbars\n            {\n                    if ((document.body.scrollHeight - document.body.clientHeight) > (document.body.scrollWidth - document.body.clientWidth)) // let's see which one is bigger\n                    {\n                            img.removeAttribute(\"style\");\n                            img.style.height = winY;\n                    }\n                    else\n                    {\n                            img.removeAttribute(\"style\");\n                            img.style.width = winX;\n                    }\n            }\n            else\n            {\n                    img.removeAttribute(\"style\");\n                    img.style.width = winX;\n            }\n    }\n    }\n    \n    function gofull() {\n        \n        var e = document.getElementById(\"fullscreen\");\n\n\t    if (RunPrefixMethod(document, \"FullScreen\") || RunPrefixMethod(document, \"IsFullScreen\")) {\n\t\t    RunPrefixMethod(document, \"CancelFullScreen\");\n\t    }\n\t    else {\n\t\t    RunPrefixMethod(e, \"RequestFullScreen\");\n\t    }\n\n    }\n\n    var pfx = [\"webkit\", \"moz\", \"ms\", \"o\", \"\"];\n    function RunPrefixMethod(obj, method) {\n\t\n\t    var p = 0, m, t;\n\t    while (p < pfx.length && !obj[m]) {\n\t    \tm = method;\n\t       \tif (pfx[p] == \"\") {\n\t    \t\tm = m.substr(0,1).toLowerCase() + m.substr(1);\n\t       \t}\n    \t\tm = pfx[p] + m;\n    \t\tt = typeof obj[m];\n    \t\tif (t != \"undefined\") {\n\t\t\t    pfx = [pfx[p]];\n\t\t\t    return (t == \"function\" ? obj[m]() : obj[m]);\n\t\t    }\n\t\t    p++;\n\t    }\n\n    }\n        \n    function doit(m) {\n        if (ws) { ws.send(m); }\n    }\n    </script>\n    </head>\n    <body onload=\"wsConnect();\" onunload=\"ws.disconnect();\">\n        <font face=\"Arial\">\n        <div id=\"messages\"></div>\n        <!-- <button type=\"button\" onclick='gofull();'>Full Screen</button> -->\n        <!-- <button type=\"button\" onclick='fit_to_screen();'>Fit</button> -->\n        <div id=\"status\">unknown</div>\n        </font>\n    </body>\n</html>\n",
        "x": 338,
        "y": 200,
        "wires": [
            [
                "b7cabbb.ce8e248"
            ]
        ]
    },
    {
        "id": "b7cabbb.ce8e248",
        "type": "http response",
        "z": "fb5b6e33.9bc11",
        "name": "",
        "x": 550,
        "y": 200,
        "wires": []
    },
    {
        "id": "bc725200.1dc2d",
        "type": "websocket-listener",
        "z": "",
        "path": "/ws/slideshow",
        "wholemsg": "false"
    }
]
juzam

Flow Info

created 3 months ago

Node Types

Core
  • change (x2)
  • http in (x1)
  • http response (x1)
  • template (x1)
  • twitter in (x1)
  • websocket out (x1)
  • websocket-listener (x1)

Tags

  • twitter
  • slideshow
  • websocket
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option