Skip to main content

Twitter Platform

@sociably/twitter platform enable your app to tweet, likes and send/receive direct messages on Twitter platform.

Install

Install the core, http and twitter packages:

npm install @sociably/core @sociably/http @sociably/twitter

Setup

First you need to apply a Twitter app and set up Account Activity API. You can follow the first 2 sections in this official guide for setup procedures.

Then set up the http and twitter modules like this:

import Sociably from '@sociably/core';
import Http from '@sociably/http';
import Twitter from '@sociably/twitter';

const {
TWITTER_APP_ID,
TWITTER_APP_KEY,
TWITTER_APP_SECRET,
TWITTER_BEARER_TOKEN,
TWITTER_ACCESS_TOKEN,
TWITTER_ACCESS_SECRET,
} = process.env;

const app = Sociably.createApp({
modules: [
Http.initModule({ port: 8080 }),
],
platforms: [
Twitter.intiModule({
webhookPath: '/webhook/twitter',
appId: TWITTER_APP_ID, // id of Twitter app
appKey: TWITTER_APP_KEY, // key of Twitter app
appSecret: TWITTER_APP_SECRET, // secret of Twitter app
bearerToken: TWITTER_BEARER_TOKEN, // bearer token of Twitter app
accessToken: TWITTER_ACCESS_TOKEN, // access token of agent user
accessSecret: TWITTER_ACCESS_SECRET, // token secret of agent user
}),
],
});

Usage

Here's an example to receive messages and send replies through direct messages.

import Sociably from '@sociably/core';
import * as Twitter from '@sociably/twitter/components';
import app from './app';

app.onEvent(async ({ platform, event, reply }) => {
if (platform === 'twitter' && event.type === 'text') {
await reply(
<Twitter.Expression
quickReplies={
<Twitter.QuickReply label="More" payload="catto" />
<Twitter.QuickReply label="I want 🐶" metadata="doggo" />
}
>
<p>Hello Twitter! 👋</p>
<Twitter.Photo url="https://cataas.com/cat" />
<p>You daily 🐱</p>
</Twitter.Expression>
);
}
});

Check API references for the details of events and components.

Webview

Auth Setup

To use webviews in Twitter, configure the app with these steps:

  1. Add auth provider to the webview platform and set app info at the basicAuth. And make sure you have a state provider installed. Like this:
import Webview from '@sociably/webview';
import RedisState from '@machiniat/redis';
import TwitterAuth from '@sociably/twitter/webview';

const app = Sociably.createApp({
platforms: [
Webview.initModule({
authPlatforms:[
TwitterAuth
],
basicAuth: {
appName: 'My Foo App',
appIconUrl: './webview/img/logo.png'
},
// ...
}),
],
modules: [
RedisState.initModule({
clientOptions: { url: REDIS_URL },
}),
],
});
  1. Expose your Twitter agent user id in next.config.js:
const { TWITTER_ACCESS_TOKEN } = process.env;

module.exports = {
publicRuntimeConfig: {
TWITTER_AGENT_ID: TWITTER_ACCESS_TOKEN.split('-', 1)[0],
},
// ...
};
  1. Set up the WebviewClient in the webview:
import getConfig from 'next/config';
import WebviewClient from '@sociably/webview/client';
import TwitterAuth from '@sociably/twitter/webview/client';

const {
publicRuntimeConfig: { TWITTER_AGENT_ID },
} = getConfig();

const client = new WebviewClient({
authPlatforms: [
new TwitterAuth({ agentId: TWITTER_AGENT_ID }),
],
});

Open the Webview

The webview can be opened with a WebviewButton in the chatroom. For example:

import * as Twitter from '@sociably/twitter/components';
import { WebviewButton as TwitterWebviewButton } from '@sociably/twitter/webview';

app.onEvent(async ({ reply }) => {
await reply(
<Twitter.DirectMessage
buttons={
<TwitterWebviewButton label="Open 📤" />
}
>
Hello Webview!
</Twitter.DirectMessage>
);
});

The user will be asked to enter a login code sent in the chat. After login, webview can communicate to the server as the authenticated user.

Check the webview platform document to learn more.

Assets Manager

TwitterAssetsManager service helps you to manage resources on the Twitter platform, like media, webhook, custom profile and welcome message.

To use it, you have to install a state provider first. Then register TwitterAssetsManager like this:

import RedisState from '@machiniat/redis';
import TwitterAssetsManager, { saveUploadedMedia } from '@sociably/twitter/asssets';

const app = Sociably.createApp({
services: [
TwitterAssetsManager,
],
platforms: [
Twitter.initModule({
dispatchMiddlewares: [
saveUploadedMedia,
]
// ...
}),
],
modules: [
RedisState.initModule({
clientOptions: { url: REDIS_URL },
}),
],
});

Here's an example to upload a reusable media from an external URL:

import fs from 'fs';
import { makeContainer } from '@sociably/core';
import * as Twitter from '@sociably/twitter/components';
import TwitterAssetsManager from '@sociably/twitter/asssets';

app.onEvent(makeContainer({ deps: [TwitterAssetsManager] })(
(assetsManager) =>
async ({ reply }) => {
const fooImageId = await assetsManager.getMedia('foo.image');

if (fooImageId) {
await reply(
<Twitter.Photo mediaId={fooImageId} />
);
} else {
await reply(
<Twitter.Photo
shared
url="https://image.from.web/url.jpg"
/>
);
}
}
));

If you upload a media with shared and assetTag props, the saveUploadedMedia middleware will save the returned media id. You can reuse the saved id for the next time.

Resources

Here are some resources for further reading: