-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #235 from knorth55/tweet-image-server
- Loading branch information
Showing
10 changed files
with
324 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,30 @@ | ||
cmake_minimum_required(VERSION 2.8.3) | ||
project(rostwitter) | ||
|
||
find_package(catkin REQUIRED COMPONENTS rospy mk) | ||
find_package(catkin REQUIRED COMPONENTS | ||
actionlib | ||
actionlib_msgs | ||
message_generation | ||
rospy | ||
std_msgs | ||
mk | ||
) | ||
|
||
catkin_python_setup() | ||
|
||
catkin_package() | ||
add_action_files( | ||
DIRECTORY action | ||
FILES Tweet.action | ||
) | ||
|
||
|
||
generate_messages( | ||
DEPENDENCIES actionlib_msgs std_msgs) | ||
|
||
catkin_package( | ||
CATKIN_DEPENDS message_runtime | ||
) | ||
|
||
install(PROGRAMS scripts/tweet.py | ||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
bool image | ||
string image_topic_name | ||
bool speak | ||
string text | ||
bool warning | ||
uint8 warning_time | ||
--- | ||
bool success | ||
--- | ||
time stamp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from rostwitter.twitter import Twitter # NOQA | ||
from rostwitter.util import load_oauth_settings # NOQA |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# originally from https://raw.githubusercontent.com/bear/python-twitter/v1.1/twitter.py # NOQA | ||
|
||
import json as simplejson | ||
import requests | ||
from requests_oauthlib import OAuth1 | ||
from StringIO import StringIO | ||
|
||
import rospy | ||
|
||
|
||
class Twitter(object): | ||
def __init__( | ||
self, | ||
consumer_key=None, | ||
consumer_secret=None, | ||
access_token_key=None, | ||
access_token_secret=None | ||
): | ||
self._consumer_key = consumer_key | ||
self._consumer_secret = consumer_secret | ||
self._access_token_key = access_token_key | ||
self._access_token_secret = access_token_secret | ||
|
||
self.__auth = OAuth1(self._consumer_key, self._consumer_secret, | ||
self._access_token_key, self._access_token_secret) | ||
self._requests_timeout = 60 | ||
|
||
def _request_url(self, url, verb, data=None): | ||
if verb == 'POST': | ||
if 'media' in data: | ||
return requests.post( | ||
url, | ||
files=data, | ||
auth=self.__auth, | ||
timeout=self._requests_timeout | ||
) | ||
else: | ||
return requests.post( | ||
url, | ||
data=data, | ||
auth=self.__auth, | ||
timeout=self._requests_timeout | ||
) | ||
if verb == 'GET': | ||
url = self._BuildUrl(url, extra_params=data) | ||
return requests.get( | ||
url, | ||
auth=self.__auth, | ||
timeout=self._requests_timeout | ||
) | ||
return 0 # if not a POST or GET request | ||
|
||
def post_update(self, status): | ||
if len(status) > 140: | ||
rospy.logwarn('tweet is too longer > 140 characters') | ||
status = status[:140] | ||
url = 'https://api.twitter.com/1.1/statuses/update.json' | ||
data = {'status': StringIO(status)} | ||
json = self._request_url(url, 'POST', data=data) | ||
data = simplejson.loads(json.content) | ||
return data | ||
|
||
def post_media(self, status, media): | ||
# 116 = 140 - len("http://t.co/ssssssssss") | ||
if len(status) > 116: | ||
rospy.logwarn('tweet wit media is too longer > 116 characters') | ||
status = status[:116] | ||
url = 'https://api.twitter.com/1.1/statuses/update_with_media.json' | ||
data = {'status': StringIO(status)} | ||
data['media'] = open(str(media), 'rb').read() | ||
json = self._request_url(url, 'POST', data=data) | ||
data = simplejson.loads(json.content) | ||
return data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import os | ||
import yaml | ||
|
||
import rospy | ||
|
||
|
||
def load_oauth_settings(yaml_path): | ||
if not os.path.exists(yaml_path): | ||
rospy.logerr('"{}" not found'.format(yaml_path)) | ||
rospy.logerr("$ get access token from https://apps.twitter.com/") | ||
rospy.logerr("cat {} <<EOF".format(yaml_path)) | ||
rospy.logerr("CKEY: xxx") | ||
rospy.logerr("CSECRET: xxx") | ||
rospy.logerr("AKEY: xxx") | ||
rospy.logerr("ASECRET: xxx") | ||
rospy.logerr("EOF") | ||
return None, None, None, None | ||
with open(yaml_path, 'r') as f: | ||
key = yaml.load(f) | ||
ckey = key['CKEY'] | ||
csecret = key['CSECRET'] | ||
akey = key['AKEY'] | ||
asecret = key['ASECRET'] | ||
return ckey, csecret, akey, asecret |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,139 +1,61 @@ | ||
#!/usr/bin/env python | ||
import imp ## for rosbuild | ||
import rospy | ||
import yaml,sys | ||
import re, os | ||
from io import BytesIO | ||
from StringIO import StringIO | ||
|
||
from std_msgs.msg import String | ||
|
||
global Api, CKEY, CSECRET, AKEY, ASECRET | ||
|
||
import requests | ||
from requests_oauthlib import OAuth1 | ||
import base64 | ||
import json as simplejson | ||
#!/usr/bin/env python | ||
|
||
# https://raw.githubusercontent.com/bear/python-twitter/v1.1/twitter.py | ||
import os | ||
import re | ||
import sys | ||
|
||
class twitter(object): | ||
def __init__(self, | ||
consumer_key=None, | ||
consumer_secret=None, | ||
access_token_key=None, | ||
access_token_secret=None): | ||
self._consumer_key = consumer_key | ||
self._consumer_secret = consumer_secret | ||
self._access_token_key = access_token_key | ||
self._access_token_secret = access_token_secret | ||
|
||
self.__auth = OAuth1(self._consumer_key, self._consumer_secret, | ||
self._access_token_key, self._access_token_secret) | ||
self._requests_timeout = 60 | ||
import rospy | ||
from std_msgs.msg import String | ||
|
||
def _RequestUrl(self, url, verb, data=None): | ||
if verb == 'POST': | ||
if data.has_key('media'): | ||
return requests.post( | ||
url, | ||
files=data, | ||
auth=self.__auth, | ||
timeout=self._requests_timeout | ||
) | ||
from rostwitter.twitter import Twitter | ||
from rostwitter.util import load_oauth_settings | ||
|
||
|
||
class Tweet(object): | ||
def __init__(self): | ||
account_info = rospy.get_param( | ||
'account_info', '/var/lib/robot/account.yaml') | ||
ckey, csecret, akey, asecret = load_oauth_settings(account_info) | ||
if not ckey or not csecret or not akey or not asecret: | ||
sys.exit(1) | ||
|
||
self.api = Twitter( | ||
consumer_key=ckey, | ||
consumer_secret=csecret, | ||
access_token_key=akey, | ||
access_token_secret=asecret) | ||
self.sub = rospy.Subscriber("tweet", String, self.tweet_cb) | ||
|
||
def tweet_cb(self, msg): | ||
message = msg.data | ||
rospy.loginfo(rospy.get_name() + " sending %s", message) | ||
|
||
# search word start from / and end with {.jpeg,.jpg,.png,.gif} | ||
m = re.search('/\S+\.(jpeg|jpg|png|gif)', message) | ||
ret = None | ||
if m: | ||
filename = m.group(0) | ||
message = re.sub(filename, "", message) | ||
if os.path.exists(filename): | ||
rospy.loginfo( | ||
rospy.get_name() + " tweet %s with file %s", | ||
message, filename) | ||
# 140 - len("http://t.co/ssssssssss") | ||
ret = self.api.post_media(message[0:116], filename) | ||
if 'errors' in ret: | ||
rospy.logerr('Failed to post: {}'.format(ret)) | ||
# ret = self.api.post_update(message) | ||
else: | ||
return requests.post( | ||
url, | ||
data=data, | ||
auth=self.__auth, | ||
timeout=self._requests_timeout | ||
) | ||
if verb == 'GET': | ||
url = self._BuildUrl(url, extra_params=data) | ||
return requests.get( | ||
url, | ||
auth=self.__auth, | ||
timeout=self._requests_timeout | ||
) | ||
return 0 # if not a POST or GET request | ||
|
||
def PostUpdate(self, status): | ||
url = 'https://api.twitter.com/1.1/statuses/update.json' | ||
|
||
data = {'status': StringIO(status)} | ||
json = self._RequestUrl(url, 'POST', data=data) | ||
data = simplejson.loads(json.content) | ||
if 'error' in data: | ||
raise Exception(data) | ||
return data | ||
|
||
def PostMedia(self, status, media): | ||
url = 'https://api.twitter.com/1.1/statuses/update_with_media.json' | ||
|
||
data = {'status': StringIO(status)} | ||
data['media'] = open(str(media), 'rb').read() | ||
json = self._RequestUrl(url, 'POST', data=data) | ||
data = simplejson.loads(json.content) | ||
if 'errors' in data: | ||
raise Exception(data) | ||
return data | ||
|
||
def tweet(dat): | ||
global Api | ||
message = dat.data | ||
rospy.loginfo(rospy.get_name() + " sending %s", message) | ||
|
||
# search word start from / and end with {.jpeg,.jpg,.png,.gif} | ||
m = re.search('/\S+\.(jpeg|jpg|png|gif)', message) | ||
ret = None | ||
if m: | ||
filename = m.group(0) | ||
message = re.sub(filename,"",message) | ||
if os.path.exists(filename): | ||
rospy.loginfo(rospy.get_name() + " tweet %s with file %s", message, filename) | ||
ret = Api.PostMedia(message[0:116], filename) # 140 - len("http://t.co/ssssssssss") | ||
#ret = Api.PostUpdate(message) | ||
rospy.logerr(rospy.get_name() + " %s could not find", filename) | ||
else: | ||
rospy.logerr(rospy.get_name() + " %s could not find", filename) | ||
else: | ||
ret = Api.PostUpdate(message[0:140]) | ||
## seg faults if message is longer than 140 byte ??? | ||
|
||
rospy.loginfo(rospy.get_name() + " receiving %s", ret) | ||
return | ||
|
||
def load_oauth_settings(): | ||
global CKEY, CSECRET, AKEY, ASECRET | ||
account_info = rospy.get_param('account_info', '/var/lib/robot/account.yaml') | ||
ret = self.api.post_update(message[0:140]) | ||
if 'errors' in ret: | ||
rospy.logerr('Failed to post: {}'.format(ret)) | ||
# seg faults if message is longer than 140 byte ??? | ||
rospy.loginfo(rospy.get_name() + " receiving %s", ret) | ||
|
||
try: | ||
key = yaml.load(open(account_info)) | ||
CKEY = key['CKEY'] | ||
CSECRET = key['CSECRET'] | ||
AKEY = key['AKEY'] | ||
ASECRET = key['ASECRET'] | ||
except IOError as e: | ||
rospy.logerr('"%s" not found'%account_info) | ||
rospy.logerr("$ get access token from https://apps.twitter.com/") | ||
rospy.logerr("cat /var/lib/robot/%s <<EOF"%account_info) | ||
rospy.logerr("CKEY: xxx") | ||
rospy.logerr("CSECRET: xxx") | ||
rospy.logerr("AKEY: xxx") | ||
rospy.logerr("ASECRET: xxx") | ||
rospy.logerr("EOF") | ||
sys.exit(-1) | ||
|
||
if __name__ == '__main__': | ||
global Api | ||
rospy.init_node('rostwitter', anonymous=True) | ||
load_oauth_settings() | ||
Api = twitter(consumer_key=CKEY, | ||
consumer_secret=CSECRET, | ||
access_token_key=AKEY, | ||
access_token_secret=ASECRET) | ||
rospy.Subscriber("tweet", String, tweet) | ||
app = Tweet() | ||
rospy.spin() | ||
|
||
|
||
|
||
|
Oops, something went wrong.