async def recv_message(self): await asyncio.sleep(0.5) return Message( body=sys.stdin.readline().rstrip(), nick=os.environ['USER'], channel='#mock', )
async def _recv_messages(self): while True: # Wait for message from client message = await self.client.recv_message() logging.debug('Received message: %s', message) # Check for matching commands async for responses in self.process_message(message): if not responses: continue if isinstance(responses, (str, Message)): responses = [responses] for response in responses: if isinstance(response, str): response = Message(response, message.nick, message.channel) await self.outgoing.put(response) # Add message to history self.history.insert(message) # Update user last seen self.update_user_seen(message.nick, message.timestamp)
async def _handle_motd(self, server): logging.debug('Handling MOTD') await self.send_message( Message( nick='NickServ', channel=None, body=f'IDENTIFY {self.password}', ))
async def tweets_timer(bot): logging.info('Tweets timer starting...') # Read configuration config = bot.config.load_module_config('tweets') templates = config.get('templates', {}) default_template = templates.get('default', TEMPLATE) # Get access token access_token = await get_access_token( bot.http_client, config['consumer_key'], config['consumer_secret'], ) # Read tweets entries = collections.defaultdict(list) cache_path = bot.config.get_config_path('tweets.cache') with dbm.open(cache_path, 'c') as cache: logging.debug('Processing tweets...') for feed in config.get('feeds', []): user = feed['user'] try: async for tweet_entry in process_feed(bot.http_client, feed, cache, access_token): entries[user].append(tweet_entry) except Exception as e: logging.warning('Unable to process %s feed: %s', user, e) logging.debug('Delivering tweets...') for user, entries in entries.items(): for entry in entries: status = entry['status'] channels = entry['channels'] status_key = entry['status_key'] status_id = entry['status_id'] link = await shorten_url(bot.http_client, entry['link']) # Send each entry to the appropriate channel for channel in channels: template = templates.get(channel, default_template) await bot.outgoing.put( Message(channel=channel, body=bot.client.format_text( template, user=user, status=status, link=link, ))) # Mark entry as delivered logging.info('Delivered %s from %s to %s', status, user, ', '.join(channels)) cache['since_id'] = str( max(int(cache.get('since_id', 1)), status_id)) cache[status_key] = str(time.time())
async def recv_message(self): await asyncio.sleep(0.1) sys.stdout.write(f'<= ') sys.stdout.flush() return Message( body = sys.stdin.readline().rstrip(), nick = os.environ['USER'], channel = '#mock', )
async def feeds_timer(bot): logging.info('Feeds timer starting...') # Read configuration config = bot.config.load_module_config('feeds') templates = config.get('templates', {}) default_template = templates.get('default', TEMPLATE) # Read and process results entries = collections.defaultdict(list) entries_limit = config.get('limit', 5) cache_path = bot.config.get_config_path('feeds.cache') with dbm.open(cache_path, 'c') as cache: logging.debug('Processing feeds...') for feed in config['feeds']: feed_title = feed['title'] try: async for feed_entry in process_feed(bot.http_client, feed, cache): entries[feed_title].append(feed_entry) except Exception as e: logging.warning('Unable to process feed %s: %s', feed_title, e) logging.debug('Delivering feeds...') for feed_title, entries in entries.items(): logging.debug('Delivering %s...', feed_title) for index, entry in enumerate( sorted(entries, key=lambda e: e['timestamp'])): if index > entries_limit: # Enforce entries limit break title = entry['title'].replace('\r', ' ').replace('\n', ' ') key = entry['link'].encode('ascii', 'ignore') link = await shorten_url(bot.http_client, entry['link']) author = entry['author'] channels = entry['channels'] logging.debug('Delivering %s...', title) # Send each entry to the appropriate channel for channel in channels: template = templates.get(channel, default_template) await bot.outgoing.put( Message(channel=channel, body=bot.client.format_text(template, feed=feed_title, title=title, link=link, author=author))) # Mark entry as delivered logging.info('Delivered %s from %s to %s', title, feed_title, ', '.join(channels)) cache[key] = str(time.time())
async def recv_message(self): message = None while not message: ws_message = await self.ws.receive() json_message = json.loads(ws_message.data) logging.debug('Received JSON: %s', json_message) if json_message.get('type') != 'message': continue try: message = Message( body = json_message['text'], nick = json_message['user'], channel = json_message['channel'], ) except KeyError: pass logging.debug('Received message: %s', message) return message
async def test_00_echo(self): for body in ('hello', 'world', 'quick brown fox'): message = await echo(None, Message(body), None) self.assertTrue(isinstance(message, Message)) self.assertEqual(message.body, body)
async def events_timer(bot): logger = logging.getLogger() logger.info('Events timer starting...') # Read configuration config = bot.config.load_module_config('events') timeout = config.get('timeout', 10 * 60) templates = config.get('templates', {}) default_template = templates.get('default', TEMPLATE) # Read events feeds for feed_config in config.get('feeds', []): feed_url = feed_config['url'] feed_title = feed_config['title'] feed_channels = feed_config.get('channels', []) logger.debug('Fetching %s (%s)', feed_title, feed_url) async with bot.http_client.get(feed_url) as response: text = await response.text() events = icalendar.Calendar.from_ical(text).walk('vevent') events = filter( lambda e: isinstance(e['DTSTART'].dt, datetime.datetime), events) logger.debug('Parsing %s (%s)', feed_title, feed_url) # Check each event for event in events: summary = event.get('summary') startdt = event.get('dtstart').dt enddt = event.get('dtend').dt exclusions = event.get('exdate') recurrences = event.get('rrule') description = event.get('description', '') location = event.get('location', '') now = datetime.datetime.now(datetime.timezone.utc) later = now + datetime.timedelta(seconds=timeout) try: channels = re.findall(r'channels:\s(.*)', description)[0].split(',') channels = list(map(str.strip, channels)) except IndexError: channels = feed_channels if recurrences: recurrences = recurrences.to_ical().decode('utf-8') starts = parse_recurrences(recurrences, startdt, exclusions) else: starts = [startdt] for start in starts: if not now <= start <= later: continue # Send each entry to the appropriate channel for channel in channels: template = templates.get(channel, default_template) await bot.outgoing.put( Message(channel=channel, body=bot.client.format_text( template, summary=summary, start_time=start.strftime("%I:%M %p"), end_time=enddt.strftime("%I:%M %p"), location=location, ))) logger.info('Delivered %s to %s', summary, ', '.join(channels))
async def _handle_private_message(self, nick, body): logging.debug('Handling Private Message: %s, %s', nick, body) return Message(body, nick)
async def _handle_channel_message(self, nick, channel, body): logging.debug('Handling Channel Message: %s, %s, %s', nick, channel, body) return Message(body, nick, channel)
async def test_00_eightball(self): message = await eightball(None, Message('!8ball'), None) for _ in range(len(RESPONSES)): self.assertTrue(isinstance(message, Message)) self.assertTrue(any(message.body in r for r in RESPONSES))