Hangouts Chat Bot image card not refreshing - google-apps-script

I am building a bot for Hangouts Chat. My bot will display a random image from a free image api. The api's URL is the same URL on each call but will get a new image. Unfortunately, my bot will not update the image. It just repost the same image on each call. I am using Google's App Script to deploy the bot. My image code is as follows:
function buildImageCard(url) {
return {
cards: [
{
sections: [
{
widgets: [
{
image: {
imageUrl: url
}
}
]
}
]
}
]
};
}
The random image shows up just like it should. The only issue is when I wan to call it again, it shows the same image. I can't seem to find a way to refresh the card. I have seen this method:
actionResponse: {type: shouldUpdate ? 'UPDATE_MESSAGE' : 'NEW_MESSAGE'},
Then pass shouldUpdate to buildImageCard. Although, nothing happens if shouldUpdate is true. What am I missing?

It seems that the problem is related with cache. Hangouts Chat is caching images so it doesn't need to download them everytime. You can try it by clearing the browser cache and updating the card with the chatbot. You should see the new image.
One thing you can do is to include a cachebreaker at the end of the url:
widgets: [
{
image: {
imageUrl: url + new Date().getTime()
}
}
]
As it's suggested here.
Also, in the same post, someone commented that this is not a good practice "as it will swamp caches (both local and upstream)". And they recommend a better solution, but in this case we cannot control Cache-Control headers.
I don't know how Hangouts Chat is managing the cache, but I guess they are taking care of it in case a bot uploads tons of different images. For example, in your case, it would be the same if you generate a new URL everytime you want to update it in the card, so I believe the cachebreaker could work for you.
I hope it helps!

Related

Reload parsedurl without having to close the app in Swift

I have an AVPlayerViewController that shows multiple short mp4 videoclips one after the other.
My only problem is: when i add new url's to my json file, i would need to close the app and open it to see the new video i added.
Is there a way that the parsedurl can be refreshed/reloaded perhaps every 10 minutes? In this case when new url's are added to the json file it will pull that information and add the new video to the end of the array, without having to close the app every time.
I was thinking of using the timer.scheduledTimer, is that possible? If so, how? And what is a better way to fix this?
EDIT:
Apparently my question is not very clear (my apologies).
I have this url:
let parseURL = "http://192.168.64.2/Project/test123.json"
The test123.json file contains:
"videos": [
{
"url" : "(Any video url)"
},
{
"url" : "(Any video url)"
}
Now, my app now shows 2 video's. If I add a 3rd url, I need to restart the simulator in order to see the 3rd video.
I want to reload/refresh the url every 10 minutes so that when changes happen in my test123.json it will be visible in the simulator without having to restart the simulator. (hope this makes everything a bit more clear)
If you really want to refresh every 10 minutes, then use timer.scheduledTimer. But a better approach would be to use silent push notifications so your server can tell your app when new content is available.

Extended devtools (chrome extension) listen tab navigation

I'm building a devtool extension and would like to inject my script again when the current page navigates to a different page:
chrome.webNavigation.onDOMContentLoaded.addListener(function(object details) { ... });
I have been on this for several days now but I can't figure out where to place the codes. Im using this template at github: https://github.com/thingsinjars/devtools-extension
I can listen to and inject script and execute scripts from the content script but I can't figure out how to listen for tab url change and inject my code/script into the next page.
I'm also, writing an extension, and even though I'm also stuck for a couple of days on a communication issue, I think I can help you to understand a little more:
First: the js file associated with the devtools will be tied with the page the devtools is currently inspecting (when I say tied it means that the related to each other, but they don't share the same context or access to google's extension api).
Second: the background page runs on its own sandbox environment and keep one instance per extension, what means that your panel my have multiple instances on different pages, but they all share the same background page.
Now to try to answer your question:
Your panel script (often called devtools.js) should send a message to your background page informing that it should start tracking the navigation of tabs, and your background page should listen for messages from any open panel of your extension and perform the necessary actions ( start tracking navigation of needed tabs and inject script after page loading):
devtools.js
chrome.runtime.sendMessage( {
message: 'track-navigation',
of: chrome.devtools.inspectedWindow.tabId
} );
background.js
var trackedTabs = [];
function injectScript( details ) {
if ( trackedTabs.indexOf( details.tabId ) ) {
chrome.tabs.executeScript( details.tabId, { file: 'include/some-script.js' } );
}
}
function trackNavigation() {
chrome.webNavigation.onDOMContentLoaded.addListener( injectScript, {
// here I've included some filtering in order to restrict urls to listen to
url: [
{ hostContains: 'www.sample.com', ports: [80, 443] },
{ hostContains: 'www.sample.local', ports: [80, 443] }
]
} );
}
chrome.runtime.onMessage.addListener( function( request, sender, sendResponse ) {
switch ( request.message ) {
case 'track-navigation':
trackedTabs.push( request.of );
trackNavigation();
break;
}
} );
While there are other ways of accomplishing the same thing (such as sending a message from the page being tracked where it is about to load, so you don't have to track pages being loaded on the background script); I think this should help you with your question.

Posting a status message to Facebook?

There's so many questions regarding Facebook's sharer.php, but they're all out of date. At first Facebook depreciated it, but according to FB's dev documentation it's now back. (Edit: And now it's going again...?)
You used to be able to use it like this:
http://www.facebook.com/sharer/sharer.php?u=<url to share>&t=<message text>
But the documentation now only mentions this:
https://www.facebook.com/sharer/sharer.php?u=<url to share>
Is it possible to set some pre-entered text into the dialogue box that appears when sharing a link on Facebook?
Thanks.
The Share dialog takes only the URL to share as parameter, nothing else (title, description, picture, …) any more. It fetches this data from the URL itself, from the Open Graph meta elements embedded into the document, or it takes a “guess” from the content if those are not present.
And even the “older” version of the Share dialog has not been taking a pre-set message parameter for a long time now – because you are not supposed to pre-fill the message in any way when sharing something, not matter what way the share actually happens. (“Not supposed to” actually meaning, Platform Policies explicitly forbid you from doing so.)
You can of course also share links via API (rather called “posting” a link then) – and because that happens in the background, the message is a parameter you specify while doing so. But the same rules apply – the message is supposed to be created by the user themselves beforehand, which effectively means they should have typed it in somewhere before. And even there it should not have been pre-filled so that they just have to press enter or click a button.
And since they announced API v2.0, all new apps will have to go through “login review” before they will be able to ask for any advanced permission (and posting a link requires one) – and with a pre-filled message in your app’s posting flow, you will definitively not get approval. Of course, you could try to “cheat” on that, and implement the pre-filling of the message only afterwards … but again, doing so is a clear violation of Platform Policies, and will get your app blocked when you are caught doing so.
And if you are planning to do this for multiple users with the same or largely similar messages, you can assume that Facebook’s algorithms will catch that quite easily.
Just one small comment - while it is not possible to edit the text as the other comments say - it is possible to edit everything going on in that page if you can install a browser extension on your client's machines (you did not specify your use case so I am mentioning this just in case you are developing something that you are able to influence in the client machine level).
For example, with a chrome extension, you can inject scripts into facebook.com domain. in the extension manifest.json:
"content_scripts": [
{
"matches": ["https://*.facebook.com/*",
And then this might be your contnet script, where you can play around with the text by hooking up to the markeup. This example sends out analytics (facebook sharer conversion rate) and changes some text (from "share" to "upload" to facebook):
sharer = (function () {
var _ref = qs('ref') ? qs('ref') : 'unknown';
function qs(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
function isSharer() {
return location.pathname === '/sharer/sharer.php';
}
function bindEvents() {
$('button[name="share"]').click(function() {
analytics.send('fb_sharer', 'share', _ref);
});
$('#u_0_0').click(function() {
analytics.send('fb_sharer', 'cancel', _ref);
});
}
function changeText() {
console.log($('.fcw').length);
$('.fcw').text('Upload to Facebook');
}
function load() {
if (!isSharer()) return;
changeText();
analytics.send('fb_sharer', 'view', _ref);
bindEvents();
}
return {
load: load
}
})();

Box iOS SDK: No on.progress call back for previewWithCallbacks

When downloading a file, I'm not getting an on.progress callback so am not able to display a progress bar. Works fine for file uploading.
What am I doing wrong?
Thanks,
Pete
BoxFile *boxFile = (BoxFile *)boxObject;
[boxFile previewWithCallbacks:^(id<BoxOperationCallbacks> on)
{
on.progress(^(NSNumber *ratio)
{
// update progress bar
});
on.after(^(BoxCallbackResponse response)
{
if (response == BoxCallbackResponseSuccessful)
{
We have the same problem but we manage to get the answer for this, although we did not try to implement it yet.
"Currently, the expected method to get progress on file downloads is
to register your object as an observer of the download queue ([Box
registerObserverForDownloadQueue:self];) and then to extend the
BoxObserver protocol and implement any of these callback methods that
you are interested in:
- (void)downloadDidBeginForItem:(BoxID *)itemID;
- (void)downloadDidProgressForItem:(BoxID *)itemID bytesDownloaded:(NSUInteger)bytes;
- (void)downloadDidCompleteForItem:(BoxID *)itemID withResponse:(BoxCallbackResponse)response;
- (void)downloadDidCompleteForAllItems;
Please remember to remove your object from the observers before you
expect your object to be deallocated because observers are currently
retained."
This question is no moot since Box have a completely new iOS SDK (v2.0), which does have the proper progress callbacks.

Modify url location in chrome extensions & stop the initial request

I've made an extension who's purpose is to redirect urls.
I.e: www.google.com becomes: www.mysite.com/?url=www.google.com
I came across this post:
How to modify current url location in chrome via extensions
The problem I'm having is that the url's are both processed. The tab initially loads up google.com and only after it's finished my request is shown ( www.mysite.com/?url=www.google.com).
Is there any way to stop the initial request from being processed?
Something like:
chrome.tabs.onUpdated.addListener(function(tabId,obj,tab){
update.stop() // ??????????? Here I'm missing...
chrome.tabs.update(tabId,{url:....}, function callback); // My update stuff..
});
Thoughts?
thank you all.
You're looking for the webNavigation API.
You can register listeners to handle user navigation by modifying or blocking the request on the fly.
In the example below, when a user navigate to www.google.com, before the page even start loading onBeforeNavigate is fired and you can redirect the user to the CSS validation page for that URL:
chrome.webNavigation.onBeforeNavigate.addListener((details) => {
if(details.url.indexOf("www.google.com") !== -1)) {
chrome.tabs.update(details.tabId, {
url: "https://jigsaw.w3.org/css-validator/validator?uri=" + details.url
});
}
});
Remember to add the "webNavigation" permission to your extension manifest to get this functionality enabled.
chrome.tabs.onUpdated is fired two times per tab load - once a tab starts loading, and another time when it finishes loading. If you attach your update to the tab start loading event then it should work relatively quickly. You will still see original url being loaded for a brief moment, but it won't wait until it finishes, as you are describing.
chrome.tabs.onUpdated.addListener(function(tabId,obj,tab){
if(obj.status == "loading") {
chrome.tabs.update(tabId,{url:....}, function callback);
}
});
I don't think there is a more efficient solution at the moment.