Qt.include("Mastodon.js") var debug = false; var loadImages = true; // used to dedupe on append/insert var knownIds = []; var max_id ; var since_id; WorkerScript.onMessage = function(msg) { if (debug) console.log("Action > " + msg.action) if (debug) console.log("Mode > " + msg.mode) // this is not elegant. it's max_id and ids from MyList // we should always get max_id on append if (msg.mode === "append" && msg.params[0]) { if ( msg.params[0]["name"] === "max_id" ) { max_id = msg.params[0]["data"] } } else if ( msg.mode === "prepend" && msg.params[0]) { // prepend could be min_id or since_id since_id = msg.params[0]["data"] } // ids are always the last param if (msg.params[2]) { if ( msg.params[2]["name"] === "ids" ) { knownIds = msg.params[2]["data"] msg.params.pop() } } /** order notifications in ASC order */ function orderNotifications(items){ for (var i = items.length-1; i > 0; i--) { if (items[i].id > 0 ) //msg.conf.notificationLastID) WorkerScript.sendMessage({ 'fireNotification': true, "data": items[i]}) } } /** Logged-in status */ if (!msg.conf || !msg.conf.login) { //console.log("Not loggedin") return; } /** Load images */ if (typeof msg.conf['loadImages'] !== "undefined") loadImages = msg.conf['loadImages'] /* init API statuses */ var API = mastodonAPI({ instance: msg.conf.instance, api_user_token: msg.conf.api_user_token}); /* * HEAD call for some actions * we have to retrieve the Link header * this falls through and continues for GET */ if (msg.action === "bookmarks" || //( msg.action === "timelines/home" && msg.mode === "append") || ( msg.action.indexOf("timelines/tag/") !== -1 ) ){ API.getLink(msg.action, msg.params, function(data) { if (debug) console.log(JSON.stringify(data)) WorkerScript.sendMessage({ 'LinkHeader': data }) }); } /** POST statuses */ if (msg.method === "POST"){ API.post(msg.action, msg.params, function(data) { if (msg.bgAction){ //console.log(JSON.stringify(data)) } else if (msg.action === "statuses") { // status posted if(msg.model){ var item = parseToot(data); msg.model.append(item) msg.model.sync(); } } else { for (var i in data) { if (data.hasOwnProperty(i)) { //console.log(JSON.stringify(data[i])) WorkerScript.sendMessage({ 'action': msg.action, 'success': true, key: i, "data": data[i]}) } } } }); return; } API.get(msg.action, msg.params, function(data) { var items = []; //console.log(data) for (var i in data) { var item; if (data.hasOwnProperty(i)) { if(msg.action === "accounts/search") { item = parseAccounts([], "", data[i]); //console.log(JSON.stringify(data[i])) console.log("has own data") items.push(item) } else if(msg.action === "notifications") { // notification //console.log("Get notification list") //console.log(JSON.stringify(data[i])) item = parseNotification(data[i]); items.push(item); } else if(msg.action.indexOf("statuses") >-1 && msg.action.indexOf("context") >-1 && i === "ancestors") { // status ancestors toots - conversation console.log("ancestors") for (var j = 0; j < data[i].length; j ++) { item = parseToot(data[i][j]); item['id'] = item['status_id']; if (typeof item['attachments'] === "undefined") item['attachments'] = []; // don't permit doubles items.push(item); //console.log(JSON.stringify(data[i][j])) } addDataToModel (msg.model, "prepend", items); items = []; //console.log(JSON.stringify(i)) } else if(msg.action.indexOf("statuses") >-1 && msg.action.indexOf("context") >-1 && i === "descendants") { // status descendants toots - conversation console.log("descendants") for (var j = 0; j < data[i].length; j ++) { item = parseToot(data[i][j]); item['id'] = item['status_id']; if (typeof item['attachments'] === "undefined") item['attachments'] = []; items.push(item); //console.log(JSON.stringify(data[i][j])) } addDataToModel (msg.model, "append", items); items = []; } else if (data[i].hasOwnProperty("content")){ //console.log("Get Toot") item = parseToot(data[i]); item['id'] = item['status_id'] items.push(item); } else { WorkerScript.sendMessage({ 'action': msg.action, 'success': true, key: i, "data": data[i] }) } } } if(msg.model && items.length) { addDataToModel(msg.model, msg.mode, items) } else { // for some reason, home chokes. console.log( "items.length = " + items.length) } /*if(msg.action === "notifications") orderNotifications(items)*/ console.log("Get em all?") WorkerScript.sendMessage({ 'updatedAll': true}) }); } //WorkerScript.sendMessage({ 'notifyNewItems': length - i }) function addDataToModel (model, mode, items) { var length = items.length; var i if (debug) console.log("Fetched > " +length + " in " + mode) if (debug) console.log("ids > " + knownIds.length ) if (mode === "append") { for(i = 0; i <= length-1; i++) { if ( knownIds.indexOf( items[i]["id"]) === -1) { model.append(items[i]) } else { console.log("nope: " + items[i]["id"] ) } } // search does not use ids if ( knownIds.length < 1 ) model.append(items) } else if (mode === "prepend") { for(i = length-1; i >= 0 ; i--) { //model.insert(0,items[i]) if ( knownIds.indexOf( items[i]["id"]) === -1) { model.insert(0,items[i]) } } } model.sync() } function findDuplicate(arr,val) { for(var i=0; i < arr.length; i++){ if( arr.indexOf(val) === -1 ) { return true; } } return false; } /* Function: Get Account Data */ function parseAccounts(collection, prefix, data) { var res = collection; // Base attributes res[prefix + 'account_id'] = data["id"] res[prefix + 'account_username'] = data["username"] res[prefix + 'account_acct'] = data["acct"] res[prefix + 'account_url'] = data["url"] // Display attributes res[prefix + 'account_display_name'] = data["display_name"] res[prefix + 'account_note'] = data["note"] res[prefix + 'account_avatar'] = data["avatar"] res[prefix + 'account_header'] = data["header"] res[prefix + 'account_locked'] = data["locked"] //res[prefix + 'account_emojis'] = data["emojis"] res[prefix + 'account_discoverable'] = data["discoverable"] // Statistical attributes res[prefix + 'account_created_at'] = data["created_at"] res[prefix + 'account_statuses_count'] = data["statuses_count"] res[prefix + 'account_followers_count'] = data["followers_count"] res[prefix + 'account_following_count'] = data["following_count"] // Optional attributes //res[prefix + 'account_fields'] = data["fields"] res[prefix + 'account_bot'] = data["bot"] res[prefix + 'account_group'] = data["group"] //console.log(JSON.stringify(res)) return (res); } /** Function: Get Notification Data */ function parseNotification(data){ //console.log(JSON.stringify(data)) var item = { id: data.id, type: data.type, attachments: [] }; switch (item['type']){ case "mention": if (!data.status) { break; } item = parseToot(data.status) item['typeIcon'] = "image://theme/icon-s-alarm" item['type'] = "mention" break; case "reblog": if (!data.status) { break; } item = parseToot(data.status) item = parseAccounts(item, "reblog_", data["account"]) item = parseAccounts(item, "", data["status"]["account"]) item['status_reblog'] = true item['type'] = "reblog" item['typeIcon'] = "image://theme/icon-s-retweet" break; case "favourite": if (!data.status) { break; } item = parseToot(data.status) item = parseAccounts(item, "reblog_", data["account"]) item = parseAccounts(item, "", data["status"]["account"]) item['status_reblog'] = true item['type'] = "favourite" item['typeIcon'] = "image://theme/icon-s-favorite" break; case "follow": item['type'] = "follow"; item = parseAccounts(item, "", data["account"]) item = parseAccounts(item, "reblog_", data["account"]) //item['content'] = data['account']['note'] item['typeIcon'] = "../../images/icon-s-follow.svg" //item['attachments'] = [] break; default: item['typeIcon'] = "image://theme/icon-s-sailfish" } item['id'] = data.id item['created_at'] = new Date(data.created_at) item['section'] = getDate(data["created_at"]) return item; } /** Function: */ function collect() { var ret = {}; var len = arguments.length; for (var i=0; i