Twitter API Javascript extended mode - javascript

I am using twitter stream API with Javascript in order to collect tweets. The problem is that I am not using the extended mode and I don't get the full tweet when it is greater than 140 characters. I have searched info and I discovered that I need to pass tweet_mode=extended in the request and the response will contain a full_text which is the tweet complete. The problem is that I don't know where to write tweet_mode=extended. This is my code:
twitter.stream('statuses/filter', {track: word, function (stream) {
stream.on('data', function (tweet) {
console.log(tweet.text)
});
stream.on('error', function (error) {
console.log("error:", error);
})
})

Unfortunately the streaming API does not have the option to add the tweet_mode param
Documentation here: https://developer.twitter.com/en/docs/tweets/tweet-updates
This paragraph is of note to your concern:
The Streaming API does not provide the same ability to provide query
parameters to configure request options. Therefore, the Streaming API
renders all Tweets in compatibility mode at this time.
...
Streaming API consumers should update their code to first check for
the presence of the extended_tweet dictionary, and use that in
preference to the truncated data as is applicable for their use case.
When extended_tweet is not present, they must fall back to using the
existing fields.

As Van said, tweets in streaming API are mixed. So you can try this :
twitter.stream('statuses/filter', {track: word, function (stream) {
stream.on('data', function (tweet) {
let text = tweet.extended_tweet?tweet.extended_tweet.full_text:tweet.full_text?tweet.full_text:tweet.text;
console.log(text)
});
stream.on('error', function (error) {
console.log("error:", error);
})
})

Related

Service Worker 'Hello World' example

I am learning about Service workers, as I have a usecase to create a fetch listener, that will pass back an arbitrary binary response.
I have no idea where to start. The examples I have seen online talk about making a server request, caching in the service worker, and passing it back. What I really want to do is just pass back my own response, not make a query to the server and cache it!
What I am looking for, as a start is, say something that will once the service worker is active, given the user enters in the browser, (or uses fetch api to get the following url)
http://myapp/helloworld
will show 'Helloworld' in the browser. The service worker will be something like the following. But I have not a clue how make it work.
self.addEventListener('fetch', event => {
// compare end of url with /helloworld
// if match, respond with 'helloword', otherwise fetch the response from the server
});
This is just going to be a very brief, broad overview of how I would tackle the problem.
First, I would follow a guide like this:
https://css-tricks.com/add-a-service-worker-to-your-site/
// Listen for request events
self.addEventListener('fetch', function (event) {
// Get the request
let request = event.request;
...
}
Then you'll use this bit of code as a guideline for what you want to do:
event.respondWith(
fetch(request).then(function (response) {
return response;
}).catch(function (error) {
return caches.match(request).then(function (response) {
return response;
});
})
);
With some modifications.
First, you'll want to check if it's a normal non-/helloworld type of request, and if it is, do something like this:
if (normalRequest) {
event.respondWith(
fetch(request).then(function (response) {
return response;
});
} else {
... TODO
}
And in the TODO section, you'll do your helloworld code - it's not clear to me what you want to do with that, so I can't really go into more detail. But this is the overall structure I would use.

Best way to structure a service in node.js/express?

I am starting to move the logic away from the routes in the express application, into a service provider. One of these routes deals with streams, not only that, it also requires some more logic to take place once the stream is finished. Here is an example of the express route.
router.get("/file-service/public/download/:id", async(req, res) => {
try {
const ID = req.params.id;
FileProvider.publicDownload(ID, (err, {file, stream}) => {
if (err) {
console.log(err.message, err.exception);
return res.status(err.code).send();
} else {
res.set('Content-Type', 'binary/octet-stream');
res.set('Content-Disposition', 'attachment; filename="' + file.filename + '"');
res.set('Content-Length', file.metadata.size);
stream.pipe(res).on("finish", () => {
FileProvider.removePublicOneTimeLink(file);
});
}
})
} catch (e) {
console.log(e);
res.status(500).send(e);
}
})
And here is one of the functions inside the service provider.
this.publicDownload = async(ID, cb) => {
const bucket = new mongoose.mongo.GridFSBucket(conn.db, {
chunkSizeBytes: 1024 * 255,
})
let file = await conn.db.collection("fs.files")
.findOne({"_id": ObjectID(ID)})
if (!file|| !file.metadata.link) {
return cb({
message: "File Not Public/Not Found",
code: 401,
exception: undefined
})
} else {
const password = process.env.KEY;
const IV = file.metadata.IV.buffer
const readStream = bucket.openDownloadStream(ObjectID(ID))
readStream.on("error", (e) => {
console.log("File service public download stream error", e);
})
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, IV);
decipher.on("error", (e) => {
console.log("File service public download decipher error", e);
})
cb(null, {
file,
stream: readStream.pipe(decipher)
})
}
}
Because it is not wise to pass res or req into the service provider (I'm guessing because of unit test).I have to return the stream inside the callback, from there I pipe that stream into the response, and also add an on finish event to remove a one-time download link for a file. Is there any way to move more of this logic into the service provider without passing res/req into it? Or am I going at this all wrong?
Is there any way to move more of this logic into the service provider without passing res/req into it?
As we've discussed in comments, you have a download operation that is part business logic and part web logic. Because you're streaming the response with custom headers, it's not as simple as "business logic get me the data and I'll manage the response completely on my own" like many classic database operations are.
If you are going to keep them completely separate while letting the download process encapsulate as much as it can, you would have to create a higher bandwidth interface between your service provider and the Express code that knows about the res object than just the one callback you have now.
Right now, you only have one operation supported and that's to pass the piped stream. But, the download code really wants to specify the content-type and size information (that's where it's known inside the download code) and it wants to know when the write stream is done so it can do its cleanup logic. And, something you don't show is proper error handling if there's an error while streaming the data to the client (with proper cleanup in that case too).
If you want to move more code into the downloader, you'd have to essentially make a little interface that allows the service code to drive more than one operation on the response, but without having an actual response object. That interface doesn't have to be a full response stream. It could just have methods on it for getting notified when the stream is done, starting the streaming, setting headers, etc...
As I've said in the comments, you will have to decide if that actually makes the code simpler or not. Design guidelines are not absolute. They are things to consider when making design choices. They shouldn't drive you in a direction that gives you code that is significantly more complicated than if made different design choices.

Status Code 422 when trying to attach a file to an outlook calendar event

I'm trying to attach a text file to an existing Event in Outlook using graph-js-sdk-web.js I believe I followed instructions exactly but I get a 422 response. How do I get it to attach a file?
I'm pretty sure my eventID is correct because I can create an event and get it by that id. I'm pretty sure that my file's post load is correct because I attached file myself and then got that event by its id expanding for attachments and it was identical OData type, name, and content.
So far I googled the response and everything I've seen is either it just works for people or they were off on their code compared to that example.
Here are permissions I'm requesting
openid profile User.Read MailboxSettings.Read Calendars.ReadWrite
This matches permissions granted to the registered app.
This is the client and file attachment code:
// Create a Graph client
var client = MicrosoftGraph.Client.init({
authProvider: (done) => {
// Just return the token
done(null, sessionStorage.accessToken);
}
});
client
.api('/me/calendar/events/' + eventID + '/attachments')
.post({
attachment: {
"#odata.type": "#microsoft.graph.fileAttachment",
name: "helloworld.txt",
contentBytes: "SGVsbG8gd29ybGQh"
}
}, (error, response) => {
if (error)
console.log(error);
else {
console.log(response);
}
});
that produced this request payload
{
"attachment":{
"#odata.type":"#microsoft.graph.fileAttachment",
"name":"helloworld.txt",
"contentBytes":"SGVsbG8gd29ybGQh"
}
}
the response I get from this is
{
"error": {
"code": "UnprocessableType",
"message": "Cannot process input of abstract type 'Microsoft.OutlookServices.Attachment'",
"innerError": {
"request-id": "0a81e9f9-ef64-4b5e-b854-65e24fb71cfb",
"date": "2019-05-14T23:57:29"
}
}
}
I'm not seeing what does it need to process attachment. What I find odd is that its abstract base class, not the one I provided in the odata.type field, which could be nothing.
I opened graph explorer and even though they don't have a working sample for attaching to event I used a post with this payload and my url and got the exact same response 422. That tells me its not the js library its something off with the graph api itself, either setup is different from their documentation or we are missing some undocumented setup requirement.
Thanks to jasonjon's help the problem is solved. In the referenced instructions there's a mismatch in the payload example and javascript code sample. I went with js sample and had parent node attachment in the payload. Turns out there is no parent node. The correct way to use that api is
client
.api('/me/calendar/events/' + eventID + '/attachments')
.post({
"#odata.type": "#microsoft.graph.fileAttachment",
name: "helloworld.txt",
contentBytes: "SGVsbG8gd29ybGQh"
}, (error, response) => {
if (error)
console.log(error);
else {
console.log(response);
}
});

Node-slack web api: chat.delete returns channel_not_found for all channels although channels.list returns all channels

I have been working on a simple chat bot using the slack-node web api and botkit, but am having some trouble using the chat.delete functionality. I am able to list out all of my channels properly, seeing their channel Id's and names, but when I try to send along the message channel with the chat.delete function, it returns "channel_not_found".
I have also tried to send along the channel name, testing with "general" and the actual channel name that I am targeting, both of which return the same error.
My bot is using a token of the admin user, which should allow deletion of any message. My bot has scope access for chat:write:bot and chat:write:user as well.
Below is a snippet of my code - I have also tried this in other places for deleting messages sent directly from the bot and get the same error, so I don't believe it has to do with permissions. I've looked into the docs and the usage seems to be correct for what I have below, but I may be missing a piece.
controller.on('ambient', function(bot, message) {
web.channels.list().then((res) => {
console.log(res); // this prints out all of the channels
// listed channels show a match for the channel ID given in message.channel
});
// this call returns an error "error: Response not OK: channel_not_found"
web.chat.delete(message.channel, message.ts).then((res) => {
console.log(res + " was deleted bc it was not tagged");
}).catch((err) => { console.log(err) });
});
The docs are a bit confusing on this, but the chat.delete method of the official #slack/client library take the parameters in a different order:
You'll want to change your code to be:
web.chat.delete(message.ts, message.chanel).then(...)
See here:
https://slackapi.github.io/node-slack-sdk/reference/ChatFacet#ChatFacet+delete

Using javascript to check if m3u8 live stream is active

Issue
I have a TVML app which calls a m3u8 live stream. The problem is that if the stream isn’t active, the video player throws an error message which cannot be customized. What I want to do is to check if the stream is live before attempting to play it. Is there a way I can accomplish this in javascript?
Error:
(update)
the TVJS playbackError event returns an IKJSError with code -1008, description: resource unavailable and domain: NSUrlErrorDomain. This Error also has an underlyingError (also IKJSError) with code -12884, description: “The operation couldn't be completed. (CoreMediaErrorDomain error -12884 - Playlist File not received)”.
The problem is that when this error is received the player immediately shows an error message on the TV which I can't replace. This is why I want to check if stream is live before attempting to play it.
Use this:
async function checkHLSActive(url) {
try {
let res = await axios.head(url);
return /2\d\d/.test('' + res.status);
} catch (err) {
console.log('err', url, err);
return false;
}
}
Don't forget to import axios library for wherever you put this.

Categories

Resources