build.rsudp.c_tweet.Tweeter._when_img()   B
last analyzed

Complexity

Conditions 7

Size

Total Lines 53
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 26.0383

Importance

Changes 0
Metric Value
eloc 41
dl 0
loc 53
ccs 10
cts 37
cp 0.2703
rs 7.496
c 0
b 0
f 0
cc 7
nop 2
crap 26.0383

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1 1
import os, sys
2 1
import time
3 1
import rsudp.raspberryshake as rs
4 1
from rsudp import printM, printW, printE, helpers
5 1
from rsudp.test import TEST
6 1
from twython import Twython
7
8
9 1
class Tweeter(rs.ConsumerThread):
10
	'''
11
	.. versionadded:: 1.0.2
12
13
		The option to add extra text to tweets using the :code:`"extra_text"`
14
		setting in settings files built by this version and later.
15
16
	.. |raspishakeq| raw:: html
17
18
		<a href="https://twitter.com/raspishakeq" target="_blank">Raspberry Shake</a>
19
20
	.. |usgsbigquakes| raw:: html
21
22
		<a href="https://twitter.com/USGSBigQuakes" target="_blank">USGS</a>
23
24
	.. |emsc_lastquake| raw:: html
25
26
		<a href="https://twitter.com/LastQuake" target="_blank">EMSC</a>
27
28
	Twitter is a social media platform sometimes used for quickly
29
	distributing public alert information. It is used by many agencies
30
	including |raspishakeq|, |usgsbigquakes|, and |emsc_lastquake|.
31
32
	.. |tw_api_bots| raw:: html
33
34
		<a href="https://developer.twitter.com/apps" target="_blank">API bots</a>
35
36
	.. note::
37
		Twitter is more difficult and stricter when it comes to making
38
		|tw_api_bots| than many services.
39
		First, you must go through a relatively rigorous process of applying for
40
		a developer account, then making a Twitter "app", and then giving the app
41
		permission to post on your behalf. See :ref:`setting-up-twitter` for details.
42
43
		Once you've gone through that process, Twitter limits posting and makes
44
		its rules on rate limiting relatively difficult to nail down.
45
		Generally, the early 2020 rate limit for posting is 300 in a 3-hour span,
46
		however that can vary depending on whether or not Twitter thinks there is
47
		suspicious activity coming from your account.
48
49
		In general, if you are looking for a simple multi-platform notification
50
		service, it may be easier and more reliable to use the Telegram service
51
		instead. rsudp has a telegram module at
52
		:py:class:`rsudp.c_telegram.Telegram`. See :ref:`setting-up-telegram` for details.
53
54
	:param str consumer_key: Twitter calls this the "consumer key"
55
	:param str consumer_secret: Twitter calls this the "consumer key secret"
56
	:param str access_token: Twitter calls this the "consumer access token"
57
	:param str access_secret: Twitter calls this the "consumer access secret"
58
	:param bool tweet_images: whether or not to send images. if False, only alerts will be sent.
59
	:type extra_text: bool or str
60
	:param extra_text: 103 additional characters to post as part of the twitter message (longer messages will be truncated).
61
	:param queue.Queue q: queue of data and messages sent by :class:`rsudp.c_consumer.Consumer`
62
63
64
	'''
65 1
	def __init__(self, consumer_key, consumer_secret, access_token, access_token_secret,
66
				 q=False, tweet_images=False, extra_text=False, testing=False,
67
				 ):
68
		"""
69
		Initialize the process
70
		"""
71 1
		super().__init__()
72 1
		self.queue = q
73 1
		self.sender = 'Tweeter'
74 1
		self.alive = True
75 1
		self.tweet_images = tweet_images
76 1
		self.testing = testing
77 1
		self.fmt = '%Y-%m-%d %H:%M:%S.%f'
78 1
		self.region = ' - region: %s' % rs.region.title() if rs.region else ''
79 1
		self.consumer_key = consumer_key
80 1
		self.consumer_secret = consumer_secret
81 1
		self.access_token = access_token
82 1
		self.access_token_secret = access_token_secret
83 1
		self.last_message = False
84
85 1
		self.extra_text = helpers.resolve_extra_text(extra_text, max_len=280, sender=self.sender)
86
87 1
		self.auth()
88
89 1
		self.livelink = u'live feed ➡️ https://stationview.raspberryshake.org/#?net=%s&sta=%s' % (rs.net, rs.stn)
90 1
		self.message0 = '(#RaspberryShake station %s.%s%s) Event detected at' % (rs.net, rs.stn, self.region)
91 1
		self.message1 = '(#RaspberryShake station %s.%s%s) Image of event detected at' % (rs.net, rs.stn, self.region)
92
93 1
		printM('Starting.', self.sender)
94
95
96 1
	def auth(self):
97 1
		if not self.testing:
98
			self.twitter = Twython(
99
				self.consumer_key,
100
				self.consumer_secret,
101
				self.access_token,
102
				self.access_token_secret
103
			)
104
		else:
105 1
			printW('The Twitter module will not post to Twitter in Testing mode.',
106
					self.sender, announce=False)
107
108
109 1
	def getq(self):
110 1
		d = self.queue.get()
111 1
		self.queue.task_done()
112
113 1
		if 'TERM' in str(d):
114 1
			self.alive = False
115 1
			printM('Exiting.', self.sender)
116 1
			sys.exit()
117
		else:
118 1
			return d
119
120
121 1
	def _when_alarm(self, d):
122
		'''
123
		Send a tweet when you get an ``ALARM`` message.
124
125
		:param bytes d: queue message
126
		'''
127 1
		event_time = helpers.fsec(helpers.get_msg_time(d))
128 1
		self.last_event_str = '%s' % (event_time.strftime(self.fmt)[:22])
129 1
		message = '%s %s UTC%s - %s' % (self.message0, self.last_event_str, self.extra_text, self.livelink)
130 1
		response = None
131 1
		try:
132 1
			printM('Tweet: %s' % (message), sender=self.sender)
133 1
			if not self.testing:
134
				response = self.twitter.update_status(status=message, lat=rs.inv[0][0].latitude,
135
														long=rs.inv[0][0].longitude,
136
														geo_enabled=True, display_coordinates=True)
137
														# location will only stick to tweets on accounts that have location enabled in Settings
138
				url = 'https://twitter.com/%s/status/%s' % (response['user']['screen_name'], response['id_str'])
139
				printM('Tweet URL: %s' % url)
140 1
			if self.testing:
141 1
				TEST['c_tweet'][1] = True
142
143
		except Exception as e:
144
			printE('could not send alert tweet - %s' % (e))
145
			try:
146
				printE('Waiting 5 seconds and trying to send tweet again...', sender=self.sender, spaces=True)
147
				time.sleep(5.1)
148
				printM('Tweet: %s' % (message), sender=self.sender)
149
				if not self.testing:
150
					self.auth()
151
					response = self.twitter.update_status(status=message, lat=rs.inv[0][0].latitude,
152
															long=rs.inv[0][0].longitude,
153
															geo_enabled=True, display_coordinates=True)
154
															# location will only stick to tweets on accounts that have location enabled in Settings
155
					url = 'https://twitter.com/%s/status/%s' % (response['user']['screen_name'], response['id_str'])
156
					printM('Tweet URL: %s' % url)
157
			except Exception as e:
158
				printE('could not send alert tweet - %s' % (e))
159
				response = None
160
161 1
		self.last_message = message
162
163
164
165 1
	def _when_img(self, d):
166
		'''
167
		Send a tweet with an image in when you get an ``IMGPATH`` message.
168
169
		:param bytes d: queue message
170
		'''
171 1
		if self.tweet_images:
172 1
			imgpath = helpers.get_msg_path(d)
173 1
			imgtime = helpers.fsec(helpers.get_msg_time(d))
174 1
			message = '%s %s UTC%s' % (self.message1, imgtime.strftime(self.fmt)[:22], self.extra_text)
175 1
			response = None
176 1
			printM('Image tweet: %s' % (message), sender=self.sender)
177 1
			if not self.testing:
178
				if os.path.exists(imgpath):
179
					with open(imgpath, 'rb') as image:
180
						try:
181
							printM('Uploading image to Twitter %s' % (imgpath), self.sender)
182
							response = self.twitter.upload_media(media=image)
183
							time.sleep(5.1)
184
							printM('Sending tweet...', sender=self.sender)
185
							response = self.twitter.update_status(status=message, media_ids=response['media_id'],
186
																	lat=rs.inv[0][0].latitude, long=rs.inv[0][0].longitude,
187
																	geo_enabled=True, display_coordinates=True)
188
																	# location will only stick to tweets on accounts that have location enabled in Settings
189
							url = 'https://twitter.com/%s/status/%s' % (response['user']['screen_name'], response['id_str'])
190
							printM('Tweet URL: %s' % url)
191
						except Exception as e:
192
							printE('could not send multimedia tweet - %s' % (e))
193
							try:
194
								printM('Waiting 5 seconds and trying to send tweet again...', sender=self.sender)
195
								time.sleep(5.1)
196
								self.auth()
197
								printM('Uploading image to Twitter (2nd try) %s' % (imgpath), self.sender)
198
								response = self.twitter.upload_media(media=image)
199
								time.sleep(5.1)
200
								printM('Sending tweet...', sender=self.sender)
201
								response = self.twitter.update_status(status=message, media_ids=response['media_id'],
202
																		lat=rs.inv[0][0].latitude, long=rs.inv[0][0].longitude,
203
																		geo_enabled=True, display_coordinates=True)
204
																		# location will only stick to tweets on accounts that have location enabled in Settings
205
								url = 'https://twitter.com/%s/status/%s' % (response['user']['screen_name'], response['id_str'])
206
								printM('Tweet URL: %s' % url)
207
208
							except Exception as e:
209
								printE('could not send multimedia tweet (2nd try) - %s' % (e))
210
								response = None
211
212
				else:
213
					printM('Could not find image: %s' % (imgpath), sender=self.sender)
214
			else:
215 1
				TEST['c_tweetimg'][1] = True
216
		
217 1
		self.last_message = message
0 ignored issues
show
introduced by
The variable message does not seem to be defined in case self.tweet_images on line 171 is False. Are you sure this can never be the case?
Loading history...
218
219 1 View Code Duplication
	def run(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
220
		"""
221
		Reads data from the queue and tweets a message if it sees an ALARM or IMGPATH message
222
		"""
223 1
		while True:
224 1
			d = self.getq()
225
226 1
			if 'ALARM' in str(d):
227 1
				self._when_alarm(d)
228
229 1
			elif 'IMGPATH' in str(d):
230
				self._when_img(d)
231