Node Twitter Streaming API 401 when passing 'follow' parameter - node.js

I'm trying to stream the timeline of another user.
I've set up an app and got all the creds, but I keep getting a 401. What am I doing wrong?
import Twitter from 'twitter';
import socketIO from 'socket.io';
import streamHandler from './../util/streamHandler';
import http from 'http';
export default function(app, serverConfig) {
const server = http.createServer(app);
const io = socketIO(server);
const twit = new Twitter(serverConfig.twitter);
twit.stream('statuses/filter', {
follow: ['76633197'],
}, (stream) => {
stream.on('data', (tweet) => {
console.log('data');
console.log(tweet.text);
});
stream.on('error', (error) => {
console.log(error);
});
});
return server;
}
serverConfig.twitter looks like:
{
consumer_key: <redacted>,
consumer_secret: <redacted>,
access_token_key: <redacted>,
access_token_secret: <redacted>
}
UPDATE: This only happens when I follow. If I pass {track: 'javascript'} as the parameter it works fine...

Related

Unable to fetch data using a simple Rest API

I created a simple Rest API using Expressjs, Prisma, SQL Server, and Docker-compose. Here is the article that I'm following. I'm trying to fetch data using that API but getting the following errors:
Error creating a database connection. (Error creating a database connection.)
at RequestHandler.handleRequestError (/app/node_modules/#prisma/client/runtime/index.js:28664:13)
at RequestHandler.request (/app/node_modules/#prisma/client/runtime/index.js:28640:12)
at async consumer (/app/node_modules/#prisma/client/runtime/index.js:29618:18)
at async PrismaClient._request (/app/node_modules/#prisma/client/runtime/index.js:29639:16) { clientVersion: '4.1.1',
errorCode: undefined }
I was able to insert data like this way:
src/index.ts:
import { PrismaClient } from '#prisma/client';
const prisma = new PrismaClient();
async function main() {
await prisma.user.create({
data: {
name: 'Alice',
email: 'alice#prisma.io',
},
});
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
But while trying to fetch that data using this API
http://localhost:8000/users the error appears.
Here is the Rest API code:
import express, { Response } from 'express';
import cors from 'cors';
import { config as dotenv } from 'dotenv';
import { PrismaClient } from '#prisma/client';
const app = express();
const prisma = new PrismaClient();
dotenv();
app.use(cors());
app.use(express.json());
app.get('/users', async (_, res: Response) => {
try {
const users = await prisma.user.findMany();
res.json(users);
} catch (err) {
return res.status(500).json({
success: false,
message: err,
});
}
});
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => console.log(`Server running in port --> ${PORT}`));

How to use socketio inside controllers?

I have a application created with Reactjs,Redux,Nodejs,MongoDB. I have created socketio in backend side.
server.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
const routes = require('./routes/api/routes');
var server = require('http').Server(app);
const io = require('./socket').init(server);
app.use(express.json());
require('dotenv').config();
mongoose.connect(process.env.MONGO_DB).then(console.log('connected'));
const corsOptions = {
credentials: true, //access-control-allow-credentials:true
optionSuccessStatus: 200,
};
app.use(cors(corsOptions));
app.use(routes);
if (
process.env.NODE_ENV === 'production' ||
process.env.NODE_ENV === 'staging'
) {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
io.on('connection', (socket) => {
console.log('New client connected');
socket.on('disconnect', () => {
console.log('Client disconnected');
});
});
server.listen(process.env.PORT || 5000, () => {
console.log('socket.io server started on port 5000');
});
socket.js
let io;
module.exports = {
init: (httpServer) => {
return (io = require('socket.io')(httpServer, {
cors: {
origin: 'http://localhost:3000',
methods: ['GET', 'POST'],
},
}));
},
getIO: () => {
if (!io) {
throw new Error('Socket.io is not initialized');
}
return io;
},
};
In controller.js I am creating new item to inside mongodb and also using socketio. I am emitting new Item that I created. It looks like that
controller.js
const createTeam = async (req, res) => {
const userId = req.user.id;
const newItem = new Item({
name: req.body.name,
owner: userId,
});
await newItem.save((err, data) => {
if (err) {
console.log(err);
return res.status(500).json({
message: 'Server Error',
});
}
});
await newItem.populate({
path: 'owner',
model: User,
select: 'name',
});
await User.findByIdAndUpdate(
userId,
{ $push: { teams: newItem } },
{ new: true }
);
io.getIO().emit('team', {
action: 'creating',
team: newItem,
});
res.json(newItem);
};
In frontend side I am listening the socketio server with socket.io-client. In my App.js I can see data that come from backend side when I console.log(data). My app working perfect until this stage. I can take the data from socketio, I can see the new client that connected. But when I send the data with dispatch, I app start to add infinite new items to database. Take a look at my App.js
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { AppNavbar } from './components/AppNavbar';
import { TeamList } from './components/TeamList';
import { loadUser } from './Store/Actions/AuthActions';
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { io } from 'socket.io-client';
import { addItems } from './Store/Actions/itemActions';
function App() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(loadUser());
const socket = io('http://localhost:5000');
socket.on('team', (data) => {
if (data.action === 'creating') {
dispatch(addItems(data.team));
}
// console.log(data);
});
}, []);
return (
<div className="App">
<AppNavbar />
<TeamList />
</div>
);
}
export default App;
My itemAction in redux side is also like that
export const addItems = (input) => (dispatch, getState) => {
axios
.post('/api/items/createTeam', input, tokenConfig(getState))
.then((res) =>
dispatch({
type: ADD_ITEM,
payload: res.data,
})
)
.catch((err) =>
dispatch(
returnErrors(err.response.data, err.response.status, 'GET_ERRORS')
)
);
};
My problem is how to stop infinite callling of api after implement socketio. How to stop infinite loop efficiently?
Infinite loop is steming from not dispatching "type: ADD_ITEM" once.This issue cause that your itemAction always would dispatch "type: ADD_ITEM" and payload with it when after every fetching then your react would re-render page again and again.
You should get rid of your dispatching action inside of addItems function and dispatch your action only inside of useEffect in App.js file .
Your code snippet should look like this in App.js:
useEffect(() => {
//...
const socket = openSocket('http://localhost:5000');
socket.on('postsChannel', (data) => {
if (data.action === 'creating') {
dispatch({ type: ADD_ITEM, payload: data.team });
}
});
}, [dispatch]);

Trouble connecting to Graphql subscriptions?

I have followed Apollo docs but seem to still be having issues connecting to subscriptions. Here is my code: On the frontend, I can see it trying to connect but is logging:
WebSocket connection to 'ws://localhost:4000/subscriptions' failed:
I have been following this: https://www.apollographql.com/docs/apollo-server/data/subscriptions/ but it seems like the documentation is slightly behind so I may be missing something.
Client:
import ReactDOM from 'react-dom';
import './index.css';
import Routes from './routes';
import 'semantic-ui-css/semantic.min.css';
import { setContext } from '#apollo/client/link/context';
import { WebSocketLink } from '#apollo/client/link/ws';
import { getMainDefinition } from '#apollo/client/utilities';
import {
ApolloProvider,
ApolloClient,
HttpLink,
InMemoryCache,
split,
} from '#apollo/client';
// Http link
const httpLink = new HttpLink({ uri: 'http://localhost:4000/graphql' });
// Websocket link
const wsLink = new WebSocketLink({
uri: 'ws://localhost:4000/subscriptions',
options: {
reconnect: true
}
});
// Attach auth headers to requests
const middlewareLink = setContext((_, { headers }) => {
// get the authentication token from local storage if it exists
const token = localStorage.getItem('token');
const refreshToken = localStorage.getItem('refreshToken');
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
x_token: token ? `${token}` : "",
x_refresh_token: refreshToken ? `${refreshToken}`: ""
}
}
});
// Combine
const httpLinkWithMiddleware = middlewareLink.concat(httpLink);
// Split link - either http or ws depending on graphql
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLinkWithMiddleware,
);
// Create client with link
const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache(),
});
// Provide client
const App = (
<ApolloProvider client={client}>
<Routes />
</ApolloProvider>
)
// Render
ReactDOM.render(
App,
document.getElementById('root')
);
Server:
import express from 'express';
import path from 'path';
import { fileLoader, mergeTypes, mergeResolvers } from 'merge-graphql-schemas';
import { ApolloServer } from 'apollo-server-express';
import { refreshTokens } from './auth';
import models from './models';
import cors from 'cors';
import jwt from 'jsonwebtoken';
const SECRET = "";
const SECRET2 = "";
const typeDefs = mergeTypes(fileLoader(path.join(__dirname, './schema')));
const resolvers = mergeResolvers(fileLoader(path.join(__dirname, './resolvers')));
const PORT = 4000;
const app = express();
// Cors
app.use(cors('*'));
// Add tokens
const addUser = async (req, res, next) => {
const token = req.headers['x_token'];
if (token) {
try {
const { user } = jwt.verify(token, SECRET);
req.user = user;
} catch (err) {
const refreshToken = req.headers['x_refresh_token'];
const newTokens = await refreshTokens(token, refreshToken, models, SECRET, SECRET2);
if (newTokens.token && newTokens.refreshToken) {
res.set('Access-Control-Expose-Headers', 'x_token', 'x_refresh_token');
res.set('x_token', newTokens.token);
res.set('x_refresh_token', newTokens.refreshToken);
}
req.user = newTokens.user;
}
}
next();
};
app.use(addUser);
// Create server
const server = new ApolloServer({
typeDefs,
resolvers,
subscriptions: {
path: '/subscriptions'
},
context: ({req, res, connection}) => {
const user = req.user;
return { models, SECRET, SECRET2, user };
},
});
// Apply middleware
server.applyMiddleware({ app });
// Sync and listen
models.sequelize.sync({force: true}).then(x => {
app.listen({ port: PORT }, () => {
console.log(`🚀 Server ready at http://localhost:${PORT}${server.graphqlPath}`);
console.log(`🚀 Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`);
}
);
});
Any help would be appreciated...
I can't see in the server declaring a websocket creation. Something like:
const WebSocket = require('ws');
const graphQLWebSocket = new WebSocket.Server({noServer: true});
Then also put in:
server.installSubscriptionHandlers(graphQLWebSocket);
After the row with server.applyMiddleware({ app });
More info here.

I am using socketio with react as the frontend and node with express js to make an app

When I am trying to connect using socketio client in the front end to the backened it is showin the error Access to XMLHttpRequest at 'http://localhost:8080/socket.io/?EIO=4&transport=polling&t=NOk7Aq9' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
front end code
import React, { Component, Fragment } from "react";
import openSocket from "socket.io-client";
import Post from "../../components/Feed/Post/Post";
import Button from "../../components/Button/Button";
import FeedEdit from "../../components/Feed/FeedEdit/FeedEdit";
import Input from "../../components/Form/Input/Input";
import Paginator from "../../components/Paginator/Paginator";
import Loader from "../../components/Loader/Loader";
import ErrorHandler from "../../components/ErrorHandler/ErrorHandler";
import "./Feed.css";
class Feed extends Component {
state = {
isEditing: false,
posts: [],
totalPosts: 0,
editPost: null,
status: "",
postPage: 1,
postsLoading: true,
editLoading: false,
};
componentDidMount() {
fetch("http://localhost:8080/feed/status", {
headers: {
Authorization: "Bearer " + this.props.token,
},
})
.then((res) => {
if (res.status !== 200) {
throw new Error("Failed to fetch user status.");
}
return res.json();
})
.then((resData) => {
console.log("status fetched ", resData.status);
this.setState({ status: resData.status });
})
.catch(this.catchError);
this.loadPosts();
console.log("openSocket", openSocket);
const socket = openSocket("http://localhost:8080/", {
transports: ["polling", "websocket"],
transportOptions: {
polling: {
extraHeaders: { "Access-Control-Allow-Origin": "*" },
},
},
});
socket.emit("connection", { data: "data" });
socket.on("posts", (data) => {
if (data.action === "create") {
this.addPost(data.post);
}
});
}
backend code
mongoose
.connect(
"mongodb://chitesh:pass123#cluster0-shard-00-00.ulx1q.mongodb.net:27017,cluster0-shard-00-01.ulx1q.mongodb.net:27017,cluster0-shard-00-02.ulx1q.mongodb.net:27017/feed?ssl=true&replicaSet=atlas-demxn2-shard-0&authSource=admin&retryWrites=true&w=majority",
{ useNewUrlParser: true, useUnifiedTopology: true }
)
.then((result) => {
const server = app.listen(8080); // this basically return us the server
const io = require("./socket.js").init(server);
// websockets uses http protocols the basis
//so we are passing our http based server to the function
// to create a websocket connection
// we are setting up a function
// to be executed whener a new connection is made
io.on("connection", (socket) => {
console.log("Client connected");
});
})
.catch((error) => {
console.log(error);
});
socket.js
const { listenerCount } = require("./models/post");
let io;
module.exports = {
init: (httpServer) => {
io = require("socket.io")(httpServer);
return io;
},
getIO: () => {
if (!io) {
let error = new Error("Socket.io is not initialized");
throw error;
}`enter code here`
return io;
},
};
Take a look at express CORS middleware.
You'll need to allow localhost:3000 to be used as origin.
You can use something like
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://localhost:3000',
}
app.use(cors(corsOptions))

Ionic/Angular change Data in Node Server

I have create a Node application that uses the Twit(twitter api) to allow my ionic/Angular Application to post a tweet on twitter, however this problem that I have is that i get a 404 error message when I set the REST method to Post, it seems to work with a GET method.
However I do not know how I can dynamically change the Data in my node application from my Ionic Application.
I want to change the User's information and the Message that is being sent, but I do not know where to start. if anyone can guide me that will be appriecated.
this is my Node server.js file
const express = require('express');
const Twitter = require('twit');
const app = express();
const client = new Twitter({
consumer_key: '...',
consumer_secret: '...',
access_token: '...',
access_token_secret: '...',
});
app.use(require('cors')());
app.use(require('body-parser').json());
app.post('/post_tweet', (req, res) => {
tweet = {status:"Random"};
client
.post(`statuses/update`, tweet)
.then(timeline => {
console.log(timeline);
res.send(timeline);
})
.catch(error => {
res.send(error);
});
});
app.listen(3000, () => console.log('Server running'));
this is my twitter service in my Ionic application
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class TwitterserviceService {
api_url = 'http://localhost:3000';
constructor(private http: HttpClient) { }
tweet(tweetdata: string) {
return this.http.get<any>(`${this.api_url}/post_tweet`)
.pipe(map(tweet => {
alert("tweet posted")
return tweet;
}));
}
}
and this is the method that I use to send a Post, however the message "this works" doesent post instead the default message in the Node application is sent "random"
sendTweet() {
this.api.tweet('this works')
.pipe(first())
.subscribe(
data => {
console.log('yes')
},
error => {
'failed'
});
}
Your service should do a POST, not a GET. And a POST must have a body.
tweet(tweetdata: string) {
return this.http.post<any>(`${this.api_url}/post_tweet`, { tweetdata })
}
note that you will have to handle this body in the express route and probably do something with this tweetdata attribute.
Alright I have found the answer and it was actually quite simple
here it the link to the resource that i am using => https://code.tutsplus.com/tutorials/connect-to-the-twitter-api-in-an-angular-6-app--cms-32315
this is my node js code
const express = require('express');
const Twitter = require('twit');
const app = express();
const client = new Twitter({
consumer_key: '...',
consumer_secret: '...',
access_token: '...',
access_token_secret: '...',
});
app.use(require('cors')());
app.use(require('body-parser').json());
app.post('/post_tweet', (req, res) => {
tweet = req.body;
client
.post(`statuses/update`, tweet)
.then(tweeting => {
console.log(tweeting);
res.send(tweeting);
})
.catch(error => {
res.send(error);
});
});
app.listen(3000, () => console.log('Server running'));
and here it the code that I have in my Ionic/Angular Project
api_url = 'http://localhost:3000';
tweet(tweetdata: string) {
return this.http.post<any>(`${this.api_url}/post_tweet/`, {status: tweetdata})
.pipe(map(tweet => {
alert("tweet posted")
return tweet;
}));
}
sendTweet() {
this.tweet('This is app code')
.pipe(first())
.subscribe(
data => {
console.log('yes')
},
error => {
'failed'
});
}
hope this helps someone.

Resources