Twitch title change via api - api

I have a little chat bot for twitch and I want to make now a function where you can change the stream title.
My function looks at the moment so:
public changeTitle = (new_title: string, callback: any): void => {
let t = this;
let request = require('request');
request.get("https://api.twitch.tv/kraken/channels/" + this.settings.current_channel + "?client_id="+this.settings.clientId, { json: true }, function (err, res) {
if (!err && res.statusCode === 200) {
let current_title = res.body.status;
console.log(current_title);
let request2 = require('request');
let options = {
url: "https://api.twitch.tv/kraken/channels/"+t.settings.current_channel+"?channel[status]="+current_title+new_title,
headers: {
"Authorization": "OAuth "+t.settings.clientId,
"Accept": "application/vnd.twitchtv.v2+json"
}
};
request2.put(options, (error: Error, response: any, body: any): void => {
console.log("Title changed?");
});
}
});
};
in the console.log(current_title) I can see the current stream title.
After the console.log("Title changed?") nothing happend.
I get the error 410 GONE. So my way to change the title is no longer supported.
Can someone show me how to change the title?
Thanks in advance :)

This looks to be covered by Update Channel
Specifically, rather than channel[status] use just status as a query param.
let options = {
url: "https://api.twitch.tv/kraken/channels/"+t.settings.current_channel+"?status="+new_title,
headers: {
"Authorization": "OAuth "+t.settings.clientId,
"Accept": "application/vnd.twitchtv.v2+json"
}
You'll also need the channel_editor scope in order to use this on a given channel.

Related

How to use Nuxt 3 server as a passthrough API with FormData to hide external endpoints

I'm trying to get my head around the Nuxt /server API and can't seem to figure out how to send a POST request with form-data (ie files) to Nuxt server to forward on to an external service:
In my pages.vue file I have this method:
async function onSubmit() {
const formData = new FormData();
for (let file of form.files) {
await formData.append("image", file);
}
await $fetch("/api/send", {
method: "POST",
body: formData
});
}
and then in /server/api/send.js I have:
export default defineEventHandler(async (event) => {
const { method } = event.node.req;
// I THINK THE ISSUE IS HERE
const body =
method !== "GET" && method !== "HEAD"
? await readMultipartFormData(event)
: undefined;
const response = await $fetch.raw(https://*******, {
method,
baseURL: *********,
headers: {
},
body: body
});
return response._data;
}
I'm effectively creating a passthrough API using Nuxt so that the external endpoint isn't exposed to the end user. Just can't figure out how to access the formData in the correct format to pass through on the server side. I don't think I am supposed to use readMultipartFormData() because that seems to be parsing the data somehow whereas I just want to pass the formData straight through to the external API. Any tips?
I've tried using both readMultipartFormData() and readBody() and neither seem to work. I don't actually need to read the body but rather get it and pass it through without any formatting...
If you want to pass the data with formdata to the endpoint try this library:
https://www.npmjs.com/package/object-to-formdata
code:
import { serialize } from 'object-to-formdata';
const formData = serialize(body);
const response = await $fetch.raw(https://*******, {
method,
baseURL: *********,
headers: {
},
body: formData
});
I managed to make it work with ugly solution, first you have to update nuxt to version 3.2.0 min then here my front side
let jobApplicationDTO = {
firstName: values.firstName,
lastName: values.lastName,
email: values.email,
phoneNumber: values.phoneNumber,
company: values.company,
shortDescription: values.shortDescription
};
const formData = new FormData();
formData.append("application", new Blob([JSON.stringify(jobApplicationDTO)], {type: "application/json"}));
formData.append("file", values.file) ;
//formData.append("file", values.file );
await useFetch("/api/application", {
method: "POST",
body: formData,
onResponse({request, response, options}) {
// Process the response data
if (response.status === 200) {
errorMessage.value = "";
successMessage.value = "Your application wa sent successfully, you will be contacted soon !";
}
},
onResponseError({request, response, options}) {
console.debug(response);
if (response.status === 400) {
successMessage.value = "";
errorMessage.value = "There may be an issue with our server. Please try again later, or send an email to support#mantiq.com";
} else {
successMessage.value = "";
errorMessage.value = "Sorry we couldn’t send the message, there may be an issue with our server. Please try again later, or send an email to support#mantiq.com";
}
},
});
}
and server side
import {FormData} from "node-fetch-native";
export default defineEventHandler(async (event) => {
const {BACKEND_REST_API, ENQUIRY_TOKEN} = useRuntimeConfig();
//retrieve frontend post formData
const form = await readMultipartFormData(event);
const applicationUrl = BACKEND_REST_API + '/job/apply'
console.log("url used for enquiry rest call :" + applicationUrl);
console.log("Job application token :" + ENQUIRY_TOKEN);
const formData = new FormData();
console.log(form);
if (form) {
formData.append(form[0].name, new Blob([JSON.stringify(JSON.parse(form[0].data))], {type: form[0].type}));
formData.append(form[1].name, new Blob([form[1].data], {type: form[1].type}), form[1].filename);
}
console.log(formData.values);
return await $fetch(applicationUrl, {
method: "POST",
body: formData,
headers: {
Authorization: ENQUIRY_TOKEN,
},
});
})
What is funny is on frontend you have to create a formData , then to get content and to recreate a formData from your previous formData converted in MultiFormPart[], i created a ticket on nuxt to see how to do it properly

Amplify Cognito Admin Query listUsersInGroup not working

I am working with AWS Amplify, specifically with Auth; I am trying to get the listUsersInGroup from Cognito pool using the next function in React:
import { Auth, API } from 'aws-amplify';
const listUsersInGroup = async (group) => {
let apiName = 'AdminQueries';
let path = '/listUsersInGroup';
let myInit = {
body: {
"groupname": group
},
headers: {
'Content-Type' : 'application/json',
Authorization: `${(await Auth.currentSession()).getAccessToken().getJwtToken()}`
}
};
const supervisorGet = await API.get(apiName, path, myInit);
}
But the API response is having code 403 and the response brings the message: {"message":"groupname is required"}
I made tests with other HTTP methods like listUsers, listGroups, listGroupsForUser and works correctly.
Can anyone help on this issue?
I found the example below in the Amplify documenation for admin actions.
It looks like the myInit object you are making is using body, but the example has queryStringParameters. That's why it's not finding the groupname key.
let nextToken;
async function listEditors(limit){
let apiName = 'AdminQueries';
let path = '/listUsersInGroup';
let myInit = {
queryStringParameters: {
"groupname": "Editors",
"limit": limit,
"token": nextToken
},
headers: {
'Content-Type' : 'application/json',
Authorization: `${(await Auth.currentSession()).getAccessToken().getJwtToken()}`
}
}
const { NextToken, ...rest } = await API.get(apiName, path, myInit);
nextToken = NextToken;
return rest;
}

Rally API create ConversationPost

with the following code I'm trying to create new conversation post for Capability. But it says
Cannot parse input stream due to I/O error as JSON document: Parse error: expected '{' but saw '￿' [ chars read = >>>￿<<< ]
function createPost(objId, post) {
objId = "313878829904";
post = "<p>MindMap:Hello from GAS.</p>"
var url = "https://rally1.rallydev.com/slm/webservice/v2.0/conversationpost/create";
var payload = {
"ConversationPost": {
"Artifact": "/portfolioitem/capability/" + objId,
"Text": post
}
}
var method = "POST";
var options = optionsPost_(method, payload);
var response = UrlFetchApp.fetch(url, optionsPost_(method, options));
var content = JSON.parse(response.getContentText());
content.CreateResult.Errors.forEach(error => Logger.log(error));
}
function optionsPost_(method, payload) {
var rallyApiKey = "";
if (rallyApiKey != "") {
PropertiesService.getScriptProperties().setProperty("RallyApiKey", rallyApiKey);
} else {
rallyApiKey = PropertiesService.getScriptProperties().getProperty("RallyApiKey");
}
if (rallyApiKey == null) return null;
return {
headers: { "ZSESSIONID": rallyApiKey },
payload: payload,
method: method
};
}
I can't spot any problem.
Could you please help?
Thank you!
Petr
I thought that from your error message, the payload might be required to be sent as JSON data. If my guessing is correct, how about the following modification?
Modified script:
From:
return {
headers: { "ZSESSIONID": rallyApiKey },
payload: payload,
method: method
};
To:
return {
headers: { "ZSESSIONID": rallyApiKey },
payload: JSON.stringify(payload),
method: method,
contentType: "application/json"
};
Note:
In this modification, it supposes that the values of payload and rallyApiKey are valid values for using the API. Please be careful this.
When above modification was not the dierct solution of your issue, can you provide the official document of API you want to use? By this, I would like to confirm it.
Reference:
fetch(url, params) of Class UrlFetchApp
Thanks for the fast response.
With the following
var payload = {"ConversationPost":{"Artifact": "/portfolioitem/capability/"+objId,"Text": post}};
var method = "POST";
var options = optionsPost_(method, payload);
and
var options={
headers: { "ZSESSIONID": rallyApiKey },
payload: payload,
method: method,
contentType:"application/json"
};
It gives me
Cannot parse input stream due to I/O error as JSON document: Parse error: expected '{' but saw 'h' [ chars read = >>>h<<< ]
If I change it to
var options={
headers: { "ZSESSIONID": rallyApiKey },
payload: JSON.stringify(payload),
method: method,
contentType:"application/json"
};
It gives me
Cannot parse input stream due to I/O error as JSON document: Parse error: expected '}' but saw ',' [ chars read = >>>{"headers":{"ZSESSIONID":"_ycHaCSd2QZSf8kbkQ0R1yhjohUvSzUYas0caApHt2A"},<<< ]
Only documentation I use is this:
https://rally1.rallydev.com/slm/doc/webservice/objectModel.sp#ConversationPost
I can't find any difference but this actually started working.
I believe the problem was caused by combination of mistakes. I removed one problem but perhaps add another one.
Here is a code which works.
function createPost(objId, post) {
objId = '313878829908';
post = "<p>MindMap:Hello from GAS.</p>"
var url = "https://rally1.rallydev.com/slm/webservice/v2.0/conversationpost/create";
var payload = {'ConversationPost':{'Artifact': '/portfolioitem/capability/'+objId,'Text': post}};
var method = 'POST';
//var options = optionsPost_(method, payload);
var response = UrlFetchApp.fetch(url, optionsPost_(method, payload));
var content = JSON.parse(response.getContentText());
content.CreateResult.Errors.forEach(error => Logger.log(error));
}
function optionsPost_(method, payload) {
var rallyApiKey = "";
if (rallyApiKey != "") {
PropertiesService.getScriptProperties().setProperty("RallyApiKey", rallyApiKey);
} else {
rallyApiKey = PropertiesService.getScriptProperties().getProperty("RallyApiKey");
}
if (rallyApiKey == null) return null;
var options={
'headers': {'ZSESSIONID': rallyApiKey },
'payload': JSON.stringify(payload),
'method': method,
'contentType':'application/json'
};
return options;
}
Thanks Tanaike for your help. I really appreciate it.

Vue.js Axios responseType blob or json object

I have an Axios request to download the .xls file. Problem is that the object returned as a response from backend doesn't always has to be a real file. If I return json object instead of file data. How I would read this json then?
Here is the function:
downloadReport() {
let postConfig = {
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
responseType: 'blob',
} as AxiosRequestConfig
axios
.post(this.urls.exportDiscountReport, this.discount.id, postConfig)
.then((response) => {
let blob = new Blob([response.data], { type: 'application/vnd.ms-excel' });
let url = window['URL'].createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = this.discount.id + ' discount draft.xlsx';
a.click();
window['URL'].revokeObjectURL(url);
})
.catch(error => {
})
}
I would like to read the response and if it contains some data in it - don't create the blob and initiate the download, instead, just show some message or whatever. If I remove the responseType: 'blob' then the .xls file downloads as unreadable and not valid file.
So the problem is that every returned response becomes blob type and I don't see my returned data in it. Any ideas?
I solved this by reading the blob response and checking if it has JSON parameter status. But this looks like an overengineering to me. Is there a better solution?
let postConfig = {
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
responseType: 'blob',
} as AxiosRequestConfig
axios
.post(this.urls.exportDiscountReport, this.discount.id, postConfig)
.then((responseBlob) => {
const self = this;
let reader = new FileReader();
reader.onload = function() {
let response = { status: true, message: '' };
try {
response = JSON.parse(<string>reader.result);
} catch (e) {}
if (response.status) {
let blob = new Blob([responseBlob.data], { type: 'application/vnd.ms-excel' });
let url = window['URL'].createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = self.discount.id + ' discount draft.xlsx';
a.click();
window['URL'].revokeObjectURL(url);
} else {
alert(response.message)
}
}
reader.readAsText(responseBlob.data);
})
.catch(error => {
})
I also found the same solution here: https://github.com/axios/axios/issues/815#issuecomment-340972365
Still looks way too hacky.
Have you tried checking the responseBlob.type property? It gives the MIME type of the returned data.
So for example you could have something like this:
const jsonMimeType = 'application/json';
const dataType = responseBlob.type;
// The instanceof Blob check here is redundant, however it's worth making sure
const isBlob = responseBlob instanceof Blob && dataType !== jsonMimeType;
if (isBlob) {
// do your blob download handling
} else {
responseBlob.text().then(text => {
const res = JSON.parse(text);
// do your JSON handling
});
}
This I find is much simpler and works for me, however it depends on your backend setup. The BLOB response is still a text response, but it's handled slightly differently.

How to change status code of headers of response in serverless framwork?

I want to response personal defined statuscode and some headers.
But I find even I change the status code to 201 the status code is still 200. and my defined header is not in headers.
my handler like:
function createResponse(status, header, body) {
return {
headers: Object.assign(header, {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json;charset=utf-8'
}),
statusCode: status,
body: JSON.stringify(body)
}
}
export const hello = async (event, context, cb) => {
const rep = {
message: 'v1.0',
event: event
};
cb(null, createResponse(201, {}, rep));
return;
};
I use serverless.yml my configuration is:
functions:
first:
handler: handlers/first.hello
events:
- http:
method: ANY
path: first
integration: lambda
How to check to correct code can change status code and response header?
I also find my headers still in response body, How to add my header part in Response headers?
If you think my intergration part have problem, can you give me correct configuration example?
Looks like you have a nested object inside headers.
Reference documentation,
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
Here is the correct sample code to send the correct response,
exports.handler = function(event, context, callback) {
console.log('Received event:', JSON.stringify(event, null, 2));
var res ={
"statusCode": 200,
"headers": {
"Content-Type": "*/*"
}
};
res.body = "Hello, World !";
callback(null, res);
};
Hope it helps.