diff --git a/README.md b/README.md index c98df12..633ac07 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Bot management commands. * !bot quit - quit the bot process (Must be done as bot owner) * !bot reload - reload all bot modules (Must be done as bot owner) * !bot stats - show statistics on matrix users seen by bot +* !bot leave - ask bot to leave this room (Must be done as admin in room) ### Help diff --git a/bot.py b/bot.py index 7f1b146..fe5204f 100755 --- a/bot.py +++ b/bot.py @@ -239,6 +239,11 @@ class Bot: self.client.access_token) await self.client.sync() + for roomid in self.client.rooms: + print(f'Bot is on {roomid} with {len(self.client.rooms[roomid].users)} users') + if len(self.client.rooms[roomid].users) == 1: + print(f'Room {roomid} has no other users - leaving it.') + print(await self.client.room_leave(roomid)) self.start() diff --git a/modules/bot.py b/modules/bot.py index a985695..f18855e 100644 --- a/modules/bot.py +++ b/modules/bot.py @@ -45,6 +45,12 @@ class MatrixModule: homeservers = homeservers[0:10] await bot.send_text(room, f'I\'m seeing {usercount} users in {roomcount} rooms. Top ten homeservers: {homeservers}') + elif args[1]=='leave': + bot.must_be_admin(room, event) + print(f'{event.sender} asked bot to leave room {room.room_id}') + await bot.send_text(room, f'By your command.') + await bot.client.room_leave(room.room_id) + else: await bot.send_text(room, 'Unknown command, sorry.') diff --git a/modules/common/pollingservice.py b/modules/common/pollingservice.py index c549afc..a1ff14f 100644 --- a/modules/common/pollingservice.py +++ b/modules/common/pollingservice.py @@ -9,6 +9,8 @@ class PollingService: self.account_rooms = dict() # Roomid -> [account, account..] self.next_poll_time = dict() # Roomid -> datetime, None = not polled yet self.service_name = "Service" + self.poll_interval_min = 30 # TODO: Configurable + self.poll_interval_random = 30 async def matrix_poll(self, bot, pollcount): if len(self.account_rooms): @@ -16,16 +18,23 @@ class PollingService: async def poll_all_accounts(self, bot): now = datetime.now() + delete_rooms = [] for roomid in self.account_rooms: - send_messages = True - # First poll - if not self.next_poll_time.get(roomid, None): - self.next_poll_time[roomid] = now + timedelta(hours=-1) - send_messages = False - if now >= self.next_poll_time.get(roomid): - accounts = self.account_rooms[roomid] - for account in accounts: - await self.poll_account(bot, account, roomid, send_messages) + if roomid in bot.client.rooms: + send_messages = True + # First poll + if not self.next_poll_time.get(roomid, None): + self.next_poll_time[roomid] = now + timedelta(hours=-1) + send_messages = False + if now >= self.next_poll_time.get(roomid): + accounts = self.account_rooms[roomid] + for account in accounts: + await self.poll_account(bot, account, roomid, send_messages) + else: + print(f'Bot is no longer in room {roomid} - deleting it from {self.service_name} room list') + delete_rooms.append(roomid) + for roomid in delete_rooms: + self.account_rooms.pop(roomid, None) self.first_run = False @@ -33,7 +42,7 @@ class PollingService: pass async def poll_account(self, bot, account, roomid, send_messages): - polldelay = timedelta(minutes=30 + randrange(30)) + polldelay = timedelta(minutes=self.poll_interval_min + randrange(self.poll_interval_random)) self.next_poll_time[roomid] = datetime.now() + polldelay await self.poll_implementation(bot, account, roomid, send_messages) @@ -45,13 +54,15 @@ class PollingService: if len(args) == 2: if args[1] == 'list': await bot.send_text(room, f'{self.service_name} accounts in this room: {self.account_rooms.get(room.room_id) or []}') - if args[1] == 'debug': + elif args[1] == 'debug': await bot.send_text(room, f"{self.service_name} accounts: {self.account_rooms.get(room.room_id) or []} - known ids: {self.known_ids}\n" \ f"Next poll in this room at {self.next_poll_time.get(room.room_id)} - in {self.next_poll_time.get(room.room_id) - datetime.now()}") elif args[1] == 'poll': bot.must_be_owner(event) + print(f'{self.service_name} force polling requested by {event.sender}') + # Faking next poll times to force poll for roomid in self.account_rooms: - self.next_poll_time[roomid] = datetime.now() + self.next_poll_time[roomid] = datetime.now() - timedelta(hours=1) await self.poll_all_accounts(bot) elif args[1] == 'clear': bot.must_be_admin(room, event) diff --git a/modules/cron.py b/modules/cron.py index af7fd2b..a823096 100644 --- a/modules/cron.py +++ b/modules/cron.py @@ -40,11 +40,18 @@ class MatrixModule: self.daily_commands = data['daily_commands'] async def matrix_poll(self, bot, pollcount): + delete_rooms = [] if self.last_hour != datetime.now().hour: self.last_hour = datetime.now().hour for room_id in self.daily_commands: - commands = self.daily_commands[room_id] - for command in commands: - if int(command['time']) == self.last_hour: - await bot.send_text(bot.get_room_by_id(room_id), command['command']) + if room_id in bot.client.rooms: + commands = self.daily_commands[room_id] + for command in commands: + if int(command['time']) == self.last_hour: + await bot.send_text(bot.get_room_by_id(room_id), command['command']) + else: + delete_rooms.append(room_id) + + for roomid in delete_rooms: + self.daily_commands.pop(roomid, None) \ No newline at end of file diff --git a/modules/teamup.py b/modules/teamup.py index eddfbde..5ae4de1 100644 --- a/modules/teamup.py +++ b/modules/teamup.py @@ -90,14 +90,21 @@ class MatrixModule: return('Polls teamup calendar.') async def poll_all_calendars(self, bot): + delete_rooms = [] for roomid in self.calendar_rooms: - calendars = self.calendar_rooms[roomid] - for calendarid in calendars: - events, timestamp = self.poll_server( - self.calendars[calendarid]) - self.calendars[calendarid].timestamp = timestamp - for event in events: - await bot.send_text(bot.get_room_by_id(roomid), 'Calendar: ' + self.eventToString(event)) + if roomid in bot.client.rooms: + calendars = self.calendar_rooms[roomid] + for calendarid in calendars: + events, timestamp = self.poll_server( + self.calendars[calendarid]) + self.calendars[calendarid].timestamp = timestamp + for event in events: + await bot.send_text(bot.get_room_by_id(roomid), 'Calendar: ' + self.eventToString(event)) + else: + delete_rooms.append(roomid) + + for roomid in delete_rooms: + self.calendar_rooms.pop(roomid, None) def poll_server(self, calendar): events, timestamp = calendar.get_changed_events(calendar.timestamp)