Подключение к Twitter API в приложении на Angular 6
() translation by (you can also view the original English article)
Из этого урока вы узнаете, как выполнить вход и подключиться к Twitter API через Node.js и Angular 6. В этом уроке мы сделаем следующее:
- авторизация через Twitter API
- отправлять записи через Twitter API
- читать ленту Twitter через Twitter API
- и многое другое!
Создание сервера Node
Начнём со сборки сервера Node, который будет обрабатывать взаимодействия с Twitter API. Сперва зарегистрируем новое приложение, чтобы получить данные для использования Twitter API.
Просто идём на https://apps.twitter.com/, создаём новое приложение и заполняем все необходимые данные, вроде название приложения, описание и URL. После создания вашего приложения, потребуется создать уникальный ключ для вашего приложения. Для этого, идём на вкладку Keys and Access Token и нажимаем кнопку Create my access token внизу страницы.
Приложение сгенерирует четыре ключа, вроде этих:
- Consumer Key (ключ API)
- Consumer Secret (секрет API)
- Access Token
- Access Token Secret
Пожалуйста запишите данные ключи, так как они пригодятся позже.
Создайте каталог для серверного кода, создайте файл .json командой npm init
и создайте файл server.js.
1 |
mkdir server
|
2 |
cd server
|
3 |
npm init |
4 |
touch server.js
|
Затем, мы установим пакет twit
и остальные зависимости, необходимые для начальной загрузки приложения Express.
1 |
npm install twit body-parser cors express
|
Пакет twit
поможет нам взаимодействовать с Twitter API. Далее в server.js инициализируем модули, создадим приложение Express и запустим сервер.
1 |
const express = require('express'); |
2 |
const Twitter = require('twit'); |
3 |
const app = express(); |
4 |
|
5 |
app.listen(3000, () => console.log('Server running')) |
Аутентификация
Потом, мы предоставим API ключи пакету twit
, как показано ниже.
1 |
const api-client = new Twitter({ |
2 |
consumer_key: 'CONSUMER_KEY', |
3 |
consumer_secret: 'CONSUMER_SECRET', |
4 |
access_token: 'ACCESS_TOKEN', |
5 |
access_token_secret: 'ACCESS_TOKEN_SECRET' |
6 |
});
|
Эти ключи уникальны для вашего приложения и связаны с вашим Twitter аккаунтом. Поэтому, когда вы делаете запрос через Twitter API, вы будете авторизированы.
Затем, на нашем сервере Node, создадим серверную часть для отправки и получения твитов.
Twitter предоставляет следующие методы подключения, которые позволят нам взаимодействовать с нашей стеной на Twitter, при получении и отправке твитов.
- GET
statuses/home_timeline
— возвращает самые недавние твиты, отправленные пользователем и пользователями, на которые он подписан. - GET
statuses/home_timeline
— возвращает самые недавние упоминания для авторизированного пользователя - POST
statuses/update
— используется для отправки твитов
Получение твитов
Первый метод будет использоваться для получения недавних твитов из вашей ленты. Мы укажем количество твитов, которые мы хотим получить.
1 |
app.get('/home_timeline', (req, res) => { |
2 |
const params = { tweet_mode: 'extended', count: 10 }; |
3 |
|
4 |
client
|
5 |
.get(`statuses/home_timeline`, params) |
6 |
.then(timeline => { |
7 |
|
8 |
res.send(timeline); |
9 |
})
|
10 |
.catch(error => { |
11 |
res.send(error); |
12 |
});
|
13 |
|
14 |
});
|
Далее API для получения всех твитов, в которых был упомянут авторизированный пользователь.
1 |
app.get('/mentions_timeline', (req, res) => { |
2 |
const params = { tweet_mode: 'extended', count: 10 }; |
3 |
|
4 |
client
|
5 |
.get(`statuses/mentions_timeline`, params) |
6 |
.then(timeline => { |
7 |
|
8 |
res.send(timeline); |
9 |
})
|
10 |
.catch(error => { |
11 |
res.send(error); |
12 |
});
|
13 |
|
14 |
});
|
Чтобы иметь возможность писать в ленту Твитера, нам понадобится изменить уровень прав доступа приложения (Access permissions) на чтение и запись (Read and write), как показано ниже.



Отправка твитов
Обновим файл server.js для вызова API для отправки твитов:
1 |
app.post('/post_tweet', (req, res) => { |
2 |
|
3 |
tweet = req.body; |
4 |
|
5 |
client
|
6 |
.post(`statuses/update`, tweet) |
7 |
.then(tweeting => { |
8 |
console.log(tweeting); |
9 |
|
10 |
res.send(tweeting); |
11 |
})
|
12 |
|
13 |
.catch(error => { |
14 |
res.send(error); |
15 |
});
|
16 |
|
17 |
|
18 |
});
|
Мы закончили с node сервером и теперь вы можете протестировать REST API с помощью Postman, чтобы убедиться, что всё работает правильно.
Проверяем серверную часть
Если вы запросите метод home_timeline
в вашем API, вы должны получить что-то вроде этого.



А вот и GET запрос для mentions_timeline
:



Серверный код, созданный нами ранее, также можно использовать для создания Твитер-бота. Ниже пример простого Твитер-бота, который обновляет статус пользователя.
1 |
const express = require('express'); |
2 |
const Twitter = require('twit'); |
3 |
|
4 |
const app = express(); |
5 |
const client = new Twitter({ |
6 |
consumer_key: 'Consumer Key Here', |
7 |
consumer_secret: 'Consumer Secret Here', |
8 |
access_token: 'Access Token Here', |
9 |
access_token_secret: 'Token Secret Here' |
10 |
});
|
11 |
|
12 |
|
13 |
app.use(require('cors')()); |
14 |
app.use(require('body-parser').json()); |
15 |
|
16 |
app.post('/post_tweet', (req, res) => { |
17 |
|
18 |
tweet = {status:"Hello world"}; |
19 |
|
20 |
client
|
21 |
.post(`statuses/update`, tweet) |
22 |
.then(timeline => { |
23 |
console.log(timeline); |
24 |
|
25 |
res.send(timeline); |
26 |
})
|
27 |
|
28 |
.catch(error => { |
29 |
res.send(error); |
30 |
});
|
31 |
|
32 |
|
33 |
});
|
34 |
|
35 |
app.listen(3000, () => console.log('Server running')); |
36 |
Построение Angular приложения для использования REST API
Сейчас мы начнём собирать наше Angular приложение, которое будет использовать API с нашего Node сервера.
Сперва, создайте приложение Angular.
1 |
ng new client |
Служба Twitter
Создадим службу Твитера, которая будет отправлять делать запросы к Node северу. Введите следующую команду в приложении Angular.
1 |
ng generate service twitterservice |
Это создаст два файла: twitter.service.ts и twitter.service.spec.ts. Откройте twitter.service.ts добавьте необходимые импорты, объявите методы API и вставьте модуль HttpClient
в конструктор.
1 |
api_url = 'https://localhost:3000'; |
2 |
|
3 |
constructor(private http: HttpClient) { } |
Затем, зададим функцию для применения REST API.
1 |
export class TwitterService { |
2 |
|
3 |
api_url = 'http://localhost:3000'; |
4 |
|
5 |
constructor(private http: HttpClient) { } |
6 |
|
7 |
getTimeline() { |
8 |
return this.http |
9 |
.get<any[]>(this.api_url+'/home_timeline') |
10 |
.pipe(map(data => data)); |
11 |
|
12 |
}
|
13 |
|
14 |
getMentions() { |
15 |
return this.http |
16 |
.get<any[]>(this.api_url+'/mentions_timeline') |
17 |
.pipe(map(data => data)); |
18 |
|
19 |
}
|
20 |
|
21 |
}
|
Доступ к службе Твитера через компонент
Чтобы получить доступ к службе Твитера из нашего компонента, нужно сгенерировать следующие компоненты.
1 |
ng generate component twitter_timeline |
2 |
ng generate component twitter_mentions |
3 |
ng generate component tweet |
Далее, в app.module.ts, задаём маршруты для сгенерированных компонентов.
1 |
import { RouterModule, Routes } from '@angular/router'; |
2 |
|
3 |
const appRoutes: Routes = [ |
4 |
{
|
5 |
path: 'twitter_timeline', |
6 |
component: TwitterTimelineComponent |
7 |
},
|
8 |
{
|
9 |
path: 'twitter_mentions', |
10 |
component: TwitterMentionsComponent |
11 |
},
|
12 |
|
13 |
{
|
14 |
path: 'tweets', |
15 |
component: TweetComponent |
16 |
},
|
17 |
|
18 |
{ path: '', |
19 |
redirectTo: '', |
20 |
pathMatch: 'full' |
21 |
}
|
22 |
];
|
Теперь откроем app.component.html и выведем компонент, как показано ниже.
1 |
<mat-toolbar color="primary"> |
2 |
<mat-toolbar-row> |
3 |
<!-- <span>HOME</span> --> |
4 |
<span><a href="/">HOME</a></span> |
5 |
<span class="spacer"></span> |
6 |
<span mat-button routerLink="/twitter_timeline">Timeline</span> |
7 |
<br> |
8 |
<a mat-button routerLink="/twitter_mentions">Mentions</a> |
9 |
<br> |
10 |
<a mat-button routerLink="/tweets">Tweets</a> |
11 |
</mat-toolbar-row> |
12 |
</mat-toolbar> |
13 |
<router-outlet></router-outlet> |
14 |
Получение твитов
Создадим два компонента для отображения наших твитов. TwitterTimelineComponent
будет отображать самые недавние твиты из ленты авторизированного пользователя, а TwitterMentionsComponent
будет отображать все твиты, в которых этот пользователь упомянут.
Начнём с TwitterTimelineComponent
. Обновите twitter-timeline.component.ts как показано ниже:
1 |
export class TwitterTimelineComponent implements OnInit { |
2 |
|
3 |
myTimeline: any; |
4 |
|
5 |
constructor(private api: TwitterService) { } |
6 |
|
7 |
ngOnInit() { |
8 |
this.getTwitterTimeline(); |
9 |
}
|
10 |
|
11 |
getTwitterTimeline(): void { |
12 |
this.api.getTimeline() |
13 |
.subscribe( |
14 |
myTimeline => { |
15 |
this.myTimeline = myTimeline; |
16 |
console.log(this.myTimeline); |
17 |
}
|
18 |
)
|
19 |
}
|
20 |
|
21 |
}
|
Метод getTwitterTimeline
использует TwitterService
для получения данных из ленты авторизированного пользователя. Обновим twitter-timeline.component.html как показано ниже.
1 |
<h1>Tweeter Timeline</h1> |
2 |
<div *ngIf="undefined === myData">Loading...</div> |
3 |
<div *ngIf="undefined !== myData"> |
4 |
<div class ="card"> |
5 |
<ng-container *ngFor="let tweets of myData.data"> |
6 |
<h3>{{tweets.full_text
|
7 |
}} |
8 |
</h3>
|
9 |
<p>{{tweets.created_at}}</p> |
10 |
<p>{{tweets.user.name}}</p> |
11 |
<p>{{tweets.user.screen_name}}</p> |
12 |
<p>{{tweets.user.location}}</p> |
13 |
<p>{{tweets.user.description}}</p> |
14 |
</ng-container>
|
15 |
</div>
|
16 |
</div>
|
17 |
Здесь мы проходимся по массиву, возвращённому методом getTwitterTimeline
и отображаем следующие атрибуты для каждого твита:
location
description
username
created_at
screen_name
Затем, перейдём к TwitterMentionsComponent и обновим его вот так:
1 |
export class TwitterMentionsComponent implements OnInit { |
2 |
|
3 |
myMentions: any; |
4 |
|
5 |
constructor(private api: TwitterService) { } |
6 |
|
7 |
ngOnInit() { |
8 |
this.getTwitterMentions(); |
9 |
}
|
10 |
|
11 |
getTwitterMentions(): void { |
12 |
this.api.getTimeline() |
13 |
.subscribe( |
14 |
myMentions => { |
15 |
this.myMentions = myMentions; |
16 |
console.log(this.myMentions); |
17 |
}
|
18 |
)
|
19 |
}
|
20 |
|
21 |
}
|
Напоследок, нам нужно отразить данные из API в нашем шаблоне. Обновляем twitter-mentions.component.html вот так:
1 |
<h1>Tweeter Mentions</h1> |
2 |
<div *ngIf="undefined === myData">Loading...</div> |
3 |
<div *ngIf="undefined !== myData"> |
4 |
<div class ="card"> |
5 |
<ng-container *ngFor="let tweets of myData.data"> |
6 |
<h3>{{tweets.full_text
|
7 |
}} |
8 |
</h3>
|
9 |
<p>{{tweets.created_at}}</p> |
10 |
<p>{{tweets.user.name}}</p> |
11 |
<p>{{tweets.user.screen_name}}</p> |
12 |
<p>{{tweets.user.location}}</p> |
13 |
<p>{{tweets.user.description}}</p> |
14 |
</ng-container>
|
15 |
</div>
|
16 |
</div>
|
17 |
Теперь, если запустите приложение, вы должны увидеть все эти атрибуты для показанных твитов.
Отправка твитов
Начнём с формы отправки данных на /post_tweet
, где зададим поле ввода и кнопку отправки, для отправки твитов. Для создания формы будем использовать модуль FormBuilder
. Добавьте следующий код в tweet.component.ts.
1 |
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
2 |
|
3 |
export class TweetComponent implements OnInit { |
4 |
tweetForm: FormGroup; |
5 |
|
6 |
constructor(private api: TwitterService private formBuilder: FormBuilder) { } |
7 |
|
8 |
ngOnInit() { |
9 |
|
10 |
this.tweetForm = this.formBuilder.group({ |
11 |
tweetdata: ['', Validators.required] |
12 |
}); |
13 |
} |
14 |
|
15 |
} |
Теперь обновите шаблон, чтобы Angular знал, какую форму использовать.
1 |
<mat-card class="contact-card"> |
2 |
<mat-card-content>
|
3 |
<form [formGroup]="tweetForm" (ngSubmit)="onSubmit()"> |
4 |
<mat-form-field>
|
5 |
<input matInput placeholder="Status" formControlName="tweetdata" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.tweetdata.errors }" > |
6 |
</mat-form-field>
|
7 |
<br>
|
8 |
<div class="form-group"> |
9 |
<button [disabled]="loading" class="btn btn-primary">TWEET</button> |
10 |
<img *ngIf="loading" src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" /> |
11 |
</div>
|
12 |
</form>
|
13 |
</mat-card-content>
|
14 |
</mat-card>
|
15 |
Как видите выше, мы добавили проверку так, чтобы форму нельзя было отправить, если она пустая.
Затем переходим к службе Twitter и добавляем туда код для отправки данных в API.
1 |
tweet(tweetdata: string) { |
2 |
return this.http.post<any>(`${this.api_url}/post_tweet/`, { status: tweetdata}) |
3 |
.pipe(map(tweet => { |
4 |
|
5 |
alert("tweet posted") |
6 |
|
7 |
return tweet; |
8 |
}));
|
9 |
}
|
10 |
|
11 |
}
|
Изменим TweetComponent
добавив туда код для вызова метода для публикации через Twitter API. Добавьте следующее в tweet.component.ts:
1 |
export class TweetComponent implements OnInit { |
2 |
tweetForm: FormGroup; |
3 |
loading = false; |
4 |
submitted = false; |
5 |
returnUrl: string; |
6 |
error = ''; |
7 |
|
8 |
constructor(private api: TwitterService private formBuilder: FormBuilder) { } |
9 |
|
10 |
ngOnInit() { |
11 |
|
12 |
this.tweetForm = this.formBuilder.group({ |
13 |
tweetdata: ['', Validators.required] |
14 |
});
|
15 |
}
|
16 |
|
17 |
get f() { return this.tweetForm.controls; } |
18 |
|
19 |
onSubmit() { |
20 |
this.submitted = true; |
21 |
|
22 |
// stop here if form is invalid
|
23 |
if (this.tweetForm.invalid) { |
24 |
return; |
25 |
}
|
26 |
|
27 |
this.loading = true; |
28 |
this.api.tweet(this.f.tweetdata.value) |
29 |
.pipe(first()) |
30 |
.subscribe( |
31 |
data => { |
32 |
console.log("yes") |
33 |
},
|
34 |
error => { |
35 |
this.error = error; |
36 |
this.loading = false; |
37 |
});
|
38 |
}
|
39 |
|
40 |
}
|
Теперь у вас должно работать: получение недавних твитов на /home_timeline
, получение упоминаний на /mentions_timeline
, и отправка твитов через /post_tweet
.
Вывод
В этом уроке вы узнали, как начать работать с Twitter API и как соорудить простого Twitter бота в несколько строк кода. Ещё вы узнали, как подключиться к REST API через Angular, включая создание API-службы и компонентов для взаимодействия с этой службой.
Чтобы узнать больше о Twitter API, посетите сайт Twitter Developers и откройте для себя бесконечные возможности.