Add twitpost bot.

This commit is contained in:
Anupam-dagar 2018-03-12 16:33:02 +05:30 committed by showell
parent b6afa030c5
commit a9a988f726
5 changed files with 246 additions and 0 deletions

View file

@ -0,0 +1,44 @@
# Twitpost Bot
Twitpost bot is a Zulip bot to tweet from zulip chat.
To use twitpost bot, you can simply call it with `@twitpost` followed
by a keyword `tweet` followed by the content to be tweeted.
For example:
`@twitpost tweet hey batman`
# Setup
Before starting using the bot, you will need:
1. consumer_key
2. consumer_secret
3. access_token
4. access_token_secret
To obtain these 4 keys, follow the following steps :
1. Login on [Twitter Application Management](https://apps.twitter.com/) using your Twitter account credentials.
2. Create a new Twitter app in the [Twitter Application Management](https://apps.twitter.com/)
3. Provide the required details (Name, Description and Website).
4. Open your app and click on `Keys and Access Tokens`.
5. This completes creation of Twitter app to get the 4 required keys.
6. Take a look at configuration section to configure the bot.
# Configuration
Enter the 4 keys in the respective field in `twitter.ini` file.
Run this bot as described in [here](https://zulipchat.com/api/running-bots#running-a-bot).
## Usage
`@twitpost tweet`
- This command tweets the given content to Twitter.
- Example Usage: `@twitpost tweet hey batman`, `@twitpost tweet hello world!`
- Sample Output:
`Tweet Posted
https://twitter.com/jasoncosta/status/243145735212777472`

View file

@ -0,0 +1,91 @@
{
"coordinates": null,
"favorited": false,
"created_at": "Wed Sep 05 00:37:15 +0000 2012",
"truncated": false,
"id_str": "243145735212777472",
"entities": {
"urls": [],
"hashtags": [
{
"text": "peterfalk",
"indices": [
35,
45
]
}
],
"user_mentions": []
},
"in_reply_to_user_id_str": null,
"text": "Maybe he'll finally find his keys. #peterfalk",
"contributors": null,
"retweet_count": 0,
"id": 243145735212777472,
"in_reply_to_status_id_str": null,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"name": "Jason Costa",
"profile_sidebar_border_color": "86A4A6",
"profile_sidebar_fill_color": "A0C5C7",
"profile_background_tile": false,
"profile_image_url": "http://a0.twimg.com/profile_images/1751674923/new_york_beard_normal.jpg",
"created_at": "Wed May 28 00:20:15 +0000 2008",
"location": "",
"is_translator": true,
"follow_request_sent": false,
"id_str": "14927800",
"profile_link_color": "FF3300",
"entities": {
"url": {
"urls": [
{
"expanded_url": "http://www.jason-costa.blogspot.com/",
"url": "http://t.co/YCA3ZKY",
"indices": [
0,
19
],
"display_url": "jason-costa.blogspot.com"
}
]
},
"description": {
"urls": []
}
},
"default_profile": false,
"contributors_enabled": false,
"url": "http://t.co/YCA3ZKY",
"favourites_count": 883,
"utc_offset": -28800,
"id": 14927800,
"profile_image_url_https": "https://si0.twimg.com/profile_images/1751674923/new_york_beard_normal.jpg",
"profile_use_background_image": true,
"listed_count": 150,
"profile_text_color": "333333",
"protected": false,
"lang": "en",
"followers_count": 8760,
"time_zone": "Pacific Time (US & Canada)",
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme6/bg.gif",
"verified": false,
"profile_background_color": "709397",
"notifications": false,
"description": "Platform at Twitter",
"geo_enabled": true,
"statuses_count": 5532,
"default_profile_image": false,
"friends_count": 166,
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme6/bg.gif",
"show_all_inline_media": true,
"screen_name": "jasoncosta",
"following": false
},
"source": "My Shiny App",
"in_reply_to_screen_name": null,
"in_reply_to_status_id": null
}

View file

@ -0,0 +1,51 @@
from zulip_bots.test_lib import (
StubBotHandler,
BotTestCase,
get_bot_message_handler,
)
from zulip_bots.test_file_utils import (
read_bot_fixture_data,
)
from unittest.mock import patch
import tweepy
import os
import json
class TestTwitpostBot(BotTestCase):
bot_name = "twitpost"
mock_config = {'consumer_key': 'abcdefghijklmnopqrstuvwxy',
'consumer_secret': 'aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyy',
'access_token': '123456789012345678-ABCDefgh1234afdsa678lKj6gHhslsi',
'access_token_secret': 'yf0SI0x6Ct2OmF0cDQc1E0eLKXrVAPFx4QkZF2f9PfFCt'}
api_response = read_bot_fixture_data('twitpost', 'api_response')
def test_bot_usage(self) -> None:
bot = get_bot_message_handler(self.bot_name)
bot_handler = StubBotHandler()
with self.mock_config_info(self.mock_config):
bot.initialize(bot_handler)
self.assertIn('This bot posts on twitter from zulip chat itself', bot.usage())
def test_bot_responds_to_empty_message(self) -> None:
with self.mock_config_info(self.mock_config):
self.verify_reply('', 'Please check help for usage.')
def test_help(self) -> None:
with self.mock_config_info(self.mock_config):
self.verify_reply('help',
"*Help for Twitter-post bot* :twitter: : \n\n"
"The bot tweets on twitter when message starts with @twitpost.\n\n"
"`@twitpost tweet <content>` will tweet on twitter with given `<content>`.\n"
"Example:\n"
" * @twitpost tweet hey batman\n")
@patch('tweepy.API.update_status', return_value=api_response)
def test_tweet(self, mockedarg):
test_message = 'tweet Maybe he\'ll finally find his keys. #peterfalk'
bot_response = 'Tweet Posted\n'\
'https://twitter.com/jasoncosta/status/243145735212777472'
with self.mock_config_info(self.mock_config):
self.verify_reply(test_message, bot_response)

View file

@ -0,0 +1,54 @@
import zulip
import tweepy
from typing import Dict, Any, Union, List, Tuple, Optional
class TwitpostBot(object):
def usage(self) -> str:
return ''' This bot posts on twitter from zulip chat itself.
Use '@twitpost help' to get more information
on the bot usage. '''
help_content = "*Help for Twitter-post bot* :twitter: : \n\n"\
"The bot tweets on twitter when message starts "\
"with @twitpost.\n\n"\
"`@twitpost tweet <content>` will tweet on twitter " \
"with given `<content>`.\n" \
"Example:\n" \
" * @twitpost tweet hey batman\n"
def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('twitter')
auth = tweepy.OAuthHandler(self.config_info['consumer_key'],
self.config_info['consumer_secret'])
auth.set_access_token(self.config_info['access_token'],
self.config_info['access_token_secret'])
self.api = tweepy.API(auth, parser=tweepy.parsers.JSONParser())
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
content = message["content"]
if content.strip() == '':
bot_handler.send_reply(message, 'Please check help for usage.')
return
if content.strip() == 'help':
bot_handler.send_reply(message, self.help_content)
return
content = content.split()
if len(content) > 1 and content[0] == "tweet":
status = self.post(" ".join(content[1:]))
screen_name = status["user"]["screen_name"]
id_str = status["id_str"]
bot_reply = "https://twitter.com/{}/status/{}".format(screen_name,
id_str)
bot_reply = "Tweet Posted\n" + bot_reply
bot_handler.send_reply(message, bot_reply)
def post(self, text):
return self.api.update_status(text)
handler_class = TwitpostBot

View file

@ -0,0 +1,6 @@
[twitter]
consumer_key=
consumer_secret=
access_token=
access_token_secret=