From f3874b8052b2db1b9d62284df66fea8d26f024d7 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sun, 13 Dec 2020 18:40:46 +0200 Subject: [PATCH] twitter urlreply --- url-twitter/plugin.json | 9 +++ url-twitter/plugin.ts | 125 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 url-twitter/plugin.json create mode 100644 url-twitter/plugin.ts diff --git a/url-twitter/plugin.json b/url-twitter/plugin.json new file mode 100644 index 0000000..b21866e --- /dev/null +++ b/url-twitter/plugin.json @@ -0,0 +1,9 @@ +{ + "main": "plugin.js", + "name": "url-twitter", + "description": "Twitter URL", + "version": "1.0.0", + "tags": ["urlreply", "twitter"], + "dependencies": ["urlreply"], + "npmDependencies": ["twitter-lite@0.14.0"] +} diff --git a/url-twitter/plugin.ts b/url-twitter/plugin.ts new file mode 100644 index 0000000..9539cb9 --- /dev/null +++ b/url-twitter/plugin.ts @@ -0,0 +1,125 @@ +import { + Plugin, + Configurable, + EventListener, + DependencyLoad +} from '@squeebot/core/lib/plugin'; + +import { logger } from '@squeebot/core/lib/core'; + +import Twitter from 'twitter-lite'; +import { IMessage } from '@squeebot/core/lib/types'; +import { sanitizeEscapedText } from '@squeebot/core/lib/common'; + +interface TwitterUser { + id: number; + name: string; + screen_name: string; + description: string; + followers_count: number; + statuses_count: number; +} + +interface TwitterTweet { + id: number; + full_text: string; + text?: string; + user: TwitterUser; + retweet_count: number; + favorite_count: number; +} + +@Configurable({ + consumer_key: null, + consumer_secret: null, + access_token_key: null, + access_token_secret: null, +}) +class TwitterURLPlugin extends Plugin { + public twitter: Twitter | null = null; + public me: TwitterUser | null = null; + + @EventListener('pluginUnload') + public unloadEventHandler(plugin: string | Plugin): void { + if (plugin === this.name || plugin === this) { + this.config.save().then(() => + this.emit('pluginUnloaded', this)); + } + } + + async handleTweet(data: TwitterTweet, msg: IMessage): Promise { + const keys = []; + const end = sanitizeEscapedText(data.text || data.full_text); + + keys.push(['field', 'Twitter', { color: 'cyan', type: 'title' }]); + keys.push(['field', data.favorite_count.toString(), { color: 'red', label: ['♥', 'Likes'], type: 'metric' }]); + keys.push(['field', data.retweet_count.toString(), { color: 'green', label: ['↱↲', 'Retweets'], type: 'metric' }]); + keys.push(['bold', '@' + data.user.screen_name + ':']); + keys.push(['field', end, { type: 'content' }]); + + msg.resolve(keys); + return true; + } + + async getStatusById(id: string): Promise { + if (!this.twitter) { + return null; + } + return this.twitter.get('statuses/show', {id, tweet_mode: 'extended'}); + } + + async twitterURLHandler(url: URL, msg: IMessage): Promise { + const det = url.href.match(/\/\w+\/status\/(\d+[^&#?\s/])/i); + if (!det) { + return false; + } + + try { + const tweet = await this.getStatusById(det[1]); + if (tweet) { + return this.handleTweet(tweet as TwitterTweet, msg); + } + } catch (e) { + msg.resolve('No such tweet!'); + } + return false; + } + + @DependencyLoad('urlreply') + addURLHandler(urlreply: any): void { + urlreply.registerHandler(this.name, 'twitter.com/', (url: URL, msg: IMessage) => { + return this.twitterURLHandler(url, msg); + }); + + urlreply.registerHandler(this.name, 'nitter.net/', (url: URL, msg: IMessage) => { + return this.twitterURLHandler(url, msg); + }); + } + + initialize(): void { + const consumerKey = this.config.get('consumer_key'); + const consumerSecret = this.config.get('consumer_secret'); + const accessToken = this.config.get('access_token_key'); + const accessTokenSecret = this.config.get('access_token_secret'); + + if (!consumerKey || !consumerSecret || !accessToken || !accessTokenSecret) { + logger.error('[%s] Twitter credentials missing!', this.name); + return; + } + + this.twitter = new Twitter({ + consumer_key: consumerKey, + consumer_secret: consumerSecret, + access_token_key: accessToken, + access_token_secret: accessTokenSecret, + }); + + this.twitter.get('account/verify_credentials').then((data: TwitterUser) => { + this.me = data; + }, (err) => { + logger.error('[%s] Twitter threw an error!', this.name, err.stack); + }); + } +} + +module.exports = TwitterURLPlugin;