extract BotModule class
This commit is contained in:
parent
80f125683f
commit
93f8c65d0c
|
@ -1,5 +1,6 @@
|
||||||
# editors
|
# editors
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
|
||||||
# ignore Pipfile.lock
|
# ignore Pipfile.lock
|
||||||
Pipfile.lock
|
Pipfile.lock
|
||||||
|
|
9
bot.py
9
bot.py
|
@ -9,10 +9,11 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
from importlib import reload
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from nio import AsyncClient, InviteEvent, JoinError, RoomMessageText
|
from nio import AsyncClient, InviteEvent, JoinError, RoomMessageText
|
||||||
from importlib import reload
|
|
||||||
|
|
||||||
# Couple of custom exceptions
|
# Couple of custom exceptions
|
||||||
|
|
||||||
|
@ -125,7 +126,8 @@ class Bot:
|
||||||
except CommandRequiresOwner:
|
except CommandRequiresOwner:
|
||||||
await self.send_text(room, f'Sorry, only bot owner can run that command.')
|
await self.send_text(room, f'Sorry, only bot owner can run that command.')
|
||||||
except Exception:
|
except Exception:
|
||||||
await self.send_text(room, f'Module {command} experienced difficulty: {sys.exc_info()[0]} - see log for details')
|
await self.send_text(room,
|
||||||
|
f'Module {command} experienced difficulty: {sys.exc_info()[0]} - see log for details')
|
||||||
traceback.print_exc(file=sys.stderr)
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
|
||||||
async def invite_cb(self, room, event):
|
async def invite_cb(self, room, event):
|
||||||
|
@ -144,6 +146,7 @@ class Bot:
|
||||||
|
|
||||||
def load_module(self, modulename):
|
def load_module(self, modulename):
|
||||||
try:
|
try:
|
||||||
|
print("load module: " + modulename)
|
||||||
module = importlib.import_module('modules.' + modulename)
|
module = importlib.import_module('modules.' + modulename)
|
||||||
module = reload(module)
|
module = reload(module)
|
||||||
cls = getattr(module, 'MatrixModule')
|
cls = getattr(module, 'MatrixModule')
|
||||||
|
@ -168,7 +171,7 @@ class Bot:
|
||||||
moduleobject = self.load_module(modulename)
|
moduleobject = self.load_module(modulename)
|
||||||
if moduleobject:
|
if moduleobject:
|
||||||
self.modules[modulename] = moduleobject
|
self.modules[modulename] = moduleobject
|
||||||
|
|
||||||
def clear_modules(self):
|
def clear_modules(self):
|
||||||
self.modules = dict()
|
self.modules = dict()
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,33 @@
|
||||||
import urllib.request
|
from datetime import datetime
|
||||||
from datetime import datetime, timedelta
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
|
|
||||||
class MatrixModule:
|
|
||||||
def matrix_start(self, bot):
|
def matrix_start(self, bot):
|
||||||
self.starttime = datetime.now()
|
self.starttime = datetime.now()
|
||||||
|
|
||||||
async def matrix_message(self, bot, room, event):
|
async def matrix_message(self, bot, room, event):
|
||||||
args = event.body.split()
|
args = event.body.split()
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
if args[1]=='quit':
|
if args[1] == 'quit':
|
||||||
bot.must_be_admin(room, event)
|
bot.must_be_admin(room, event)
|
||||||
await bot.send_text(room, f'Quitting, as requested')
|
await bot.send_text(room, f'Quitting, as requested')
|
||||||
print(f'{event.sender} commanded bot to quit, so quitting..')
|
print(f'{event.sender} commanded bot to quit, so quitting..')
|
||||||
bot.bot_task.cancel()
|
bot.bot_task.cancel()
|
||||||
elif args[1]=='version':
|
elif args[1] == 'version':
|
||||||
await bot.send_text(room, f'Hemppa version {bot.version} - https://github.com/vranki/hemppa')
|
await bot.send_text(room, f'Hemppa version {bot.version} - https://github.com/vranki/hemppa')
|
||||||
elif args[1]=='reload':
|
elif args[1] == 'reload':
|
||||||
bot.must_be_admin(room, event)
|
bot.must_be_admin(room, event)
|
||||||
await bot.send_text(room, f'Reloading modules..')
|
await bot.send_text(room, f'Reloading modules..')
|
||||||
bot.stop()
|
bot.stop()
|
||||||
bot.reload_modules()
|
bot.reload_modules()
|
||||||
bot.start()
|
bot.start()
|
||||||
elif args[1]=='status':
|
elif args[1] == 'status':
|
||||||
uptime = datetime.now() - self.starttime
|
uptime = datetime.now() - self.starttime
|
||||||
await bot.send_text(room, f'Uptime {uptime} - system time is {datetime.now()} - loaded {len(bot.modules)} modules.')
|
await bot.send_text(room,
|
||||||
elif args[1]=='stats':
|
f'Uptime {uptime} - system time is {datetime.now()} - loaded {len(bot.modules)} modules.')
|
||||||
|
elif args[1] == 'stats':
|
||||||
roomcount = len(bot.client.rooms)
|
roomcount = len(bot.client.rooms)
|
||||||
usercount = 0
|
usercount = 0
|
||||||
homeservers = dict()
|
homeservers = dict()
|
||||||
|
@ -44,8 +47,9 @@ class MatrixModule:
|
||||||
if len(homeservers) > 10:
|
if len(homeservers) > 10:
|
||||||
homeservers = homeservers[0:10]
|
homeservers = homeservers[0:10]
|
||||||
|
|
||||||
await bot.send_text(room, f'I\'m seeing {usercount} users in {roomcount} rooms. Top ten homeservers: {homeservers}')
|
await bot.send_text(room,
|
||||||
elif args[1]=='leave':
|
f'I\'m seeing {usercount} users in {roomcount} rooms. Top ten homeservers: {homeservers}')
|
||||||
|
elif args[1] == 'leave':
|
||||||
bot.must_be_admin(room, event)
|
bot.must_be_admin(room, event)
|
||||||
print(f'{event.sender} asked bot to leave room {room.room_id}')
|
print(f'{event.sender} asked bot to leave room {room.room_id}')
|
||||||
await bot.send_text(room, f'By your command.')
|
await bot.send_text(room, f'By your command.')
|
||||||
|
@ -55,4 +59,4 @@ class MatrixModule:
|
||||||
await bot.send_text(room, 'Unknown command, sorry.')
|
await bot.send_text(room, 'Unknown command, sorry.')
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Bot management commands')
|
return 'Bot management commands'
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from nio import RoomMessageText, Event
|
||||||
|
|
||||||
|
|
||||||
|
class BotModule(ABC):
|
||||||
|
"""Abtract bot module
|
||||||
|
|
||||||
|
A module derives from this class to process and interact on room messages. The subcluss must be named `MatrixModule`.
|
||||||
|
Just write a python file with desired command name and place it in modules. See current modules for examples.
|
||||||
|
|
||||||
|
No need to register it anywhere else.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
|
async def matrix_message(self, bot, room, event):
|
||||||
|
args = event.body.split()
|
||||||
|
args.pop(0)
|
||||||
|
|
||||||
|
# Echo what they said back
|
||||||
|
await bot.send_text(room, ' '.join(args))
|
||||||
|
|
||||||
|
def help(self):
|
||||||
|
return 'Echoes back what user has said'
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def matrix_start(self, bot):
|
||||||
|
"""Called once on startup
|
||||||
|
|
||||||
|
:param bot: a reference to the bot
|
||||||
|
:type bot: Bot
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def matrix_message(self, bot, room, event):
|
||||||
|
"""Called when a message is sent to room starting with !module_name
|
||||||
|
|
||||||
|
:param bot: a reference to the bot
|
||||||
|
:type bot: Bot
|
||||||
|
:param room: a matrix room message
|
||||||
|
:type room: RoomMessageText
|
||||||
|
:param event: a handle to the event that triggered the callback
|
||||||
|
:type event: Event
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def matrix_stop(self, bot):
|
||||||
|
"""Called once before exit
|
||||||
|
|
||||||
|
:param bot: a reference to the bot
|
||||||
|
:type bot: Bot
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def matrix_poll(self, bot, pollcount):
|
||||||
|
"""Called every 10 seconds
|
||||||
|
|
||||||
|
:param bot: a reference to the bot
|
||||||
|
:type bot: Bot
|
||||||
|
:param pollcount: the actual poll count
|
||||||
|
:type pollcount: int
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def help(self):
|
||||||
|
"""Return one-liner help text"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_settings(self):
|
||||||
|
"""Must return a dict object that can be converted to JSON and sent to server
|
||||||
|
|
||||||
|
:return: a dict object that can be converted to JSON
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_settings(self, data):
|
||||||
|
"""Load these settings. It should be the same JSON you returned in previous get_settings
|
||||||
|
|
||||||
|
:param data: a dict object containing the settings read from the account
|
||||||
|
:type data: dict
|
||||||
|
"""
|
||||||
|
pass
|
|
@ -1,15 +1,14 @@
|
||||||
import traceback
|
|
||||||
import sys
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from random import randrange
|
from random import randrange
|
||||||
|
|
||||||
|
|
||||||
class PollingService:
|
class PollingService:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.known_ids = set()
|
self.known_ids = set()
|
||||||
self.account_rooms = dict() # Roomid -> [account, account..]
|
self.account_rooms = dict() # Roomid -> [account, account..]
|
||||||
self.next_poll_time = dict() # Roomid -> datetime, None = not polled yet
|
self.next_poll_time = dict() # Roomid -> datetime, None = not polled yet
|
||||||
self.service_name = "Service"
|
self.service_name = "Service"
|
||||||
self.poll_interval_min = 30 # TODO: Configurable
|
self.poll_interval_min = 30 # TODO: Configurable
|
||||||
self.poll_interval_random = 30
|
self.poll_interval_random = 30
|
||||||
|
|
||||||
async def matrix_poll(self, bot, pollcount):
|
async def matrix_poll(self, bot, pollcount):
|
||||||
|
@ -47,16 +46,17 @@ class PollingService:
|
||||||
|
|
||||||
await self.poll_implementation(bot, account, roomid, send_messages)
|
await self.poll_implementation(bot, account, roomid, send_messages)
|
||||||
|
|
||||||
|
|
||||||
async def matrix_message(self, bot, room, event):
|
async def matrix_message(self, bot, room, event):
|
||||||
args = event.body.split()
|
args = event.body.split()
|
||||||
|
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
if args[1] == 'list':
|
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 []}')
|
await bot.send_text(room,
|
||||||
|
f'{self.service_name} accounts in this room: {self.account_rooms.get(room.room_id) or []}')
|
||||||
elif 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" \
|
await bot.send_text(room,
|
||||||
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()}")
|
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':
|
elif args[1] == 'poll':
|
||||||
bot.must_be_owner(event)
|
bot.must_be_owner(event)
|
||||||
print(f'{self.service_name} force polling requested by {event.sender}')
|
print(f'{self.service_name} force polling requested by {event.sender}')
|
||||||
|
@ -111,4 +111,4 @@ class PollingService:
|
||||||
self.account_rooms = data['account_rooms']
|
self.account_rooms = data['account_rooms']
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return(f'{self.service_name} polling')
|
return f'{self.service_name} polling'
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import shlex
|
import shlex
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from .common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
class MatrixModule:
|
class MatrixModule(BotModule):
|
||||||
daily_commands = dict() # room_id -> command json
|
daily_commands = dict() # room_id -> command json
|
||||||
last_hour = datetime.now().hour
|
last_hour = datetime.now().hour
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ class MatrixModule:
|
||||||
await bot.send_text(room, 'Cleared commands on this room.')
|
await bot.send_text(room, 'Cleared commands on this room.')
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Runs scheduled commands')
|
return ('Runs scheduled commands')
|
||||||
|
|
||||||
def get_settings(self):
|
def get_settings(self):
|
||||||
return {'daily_commands': self.daily_commands}
|
return {'daily_commands': self.daily_commands}
|
||||||
|
@ -54,4 +55,4 @@ class MatrixModule:
|
||||||
delete_rooms.append(room_id)
|
delete_rooms.append(room_id)
|
||||||
|
|
||||||
for roomid in delete_rooms:
|
for roomid in delete_rooms:
|
||||||
self.daily_commands.pop(roomid, None)
|
self.daily_commands.pop(roomid, None)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
class MatrixModule:
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
async def matrix_message(self, bot, room, event):
|
async def matrix_message(self, bot, room, event):
|
||||||
args = event.body.split()
|
args = event.body.split()
|
||||||
args.pop(0)
|
args.pop(0)
|
||||||
|
@ -7,4 +10,4 @@ class MatrixModule:
|
||||||
await bot.send_text(room, ' '.join(args))
|
await bot.send_text(room, ' '.join(args))
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Echoes back what user has said')
|
return ('Echoes back what user has said')
|
||||||
|
|
|
@ -9,6 +9,7 @@ from google.auth.transport.requests import Request
|
||||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||||
from googleapiclient.discovery import build
|
from googleapiclient.discovery import build
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Google calendar notifications
|
# Google calendar notifications
|
||||||
#
|
#
|
||||||
|
@ -16,9 +17,10 @@ from googleapiclient.discovery import build
|
||||||
# It's created on first run (run from console!) and
|
# It's created on first run (run from console!) and
|
||||||
# can be copied to another computer.
|
# can be copied to another computer.
|
||||||
#
|
#
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
class MatrixModule:
|
class MatrixModule(BotModule):
|
||||||
def matrix_start(self, bot):
|
def matrix_start(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
||||||
|
@ -135,7 +137,8 @@ class MatrixModule:
|
||||||
async def send_events(self, bot, events, room):
|
async def send_events(self, bot, events, room):
|
||||||
for event in events:
|
for event in events:
|
||||||
start = event['start'].get('dateTime', event['start'].get('date'))
|
start = event['start'].get('dateTime', event['start'].get('date'))
|
||||||
await bot.send_html(room, f'{self.parse_date(start)} <a href="{event["htmlLink"]}">{event["summary"]}</a>', f'{self.parse_date(start)} {event["summary"]}')
|
await bot.send_html(room, f'{self.parse_date(start)} <a href="{event["htmlLink"]}">{event["summary"]}</a>',
|
||||||
|
f'{self.parse_date(start)} {event["summary"]}')
|
||||||
|
|
||||||
def list_upcoming(self, calid):
|
def list_upcoming(self, calid):
|
||||||
startTime = datetime.utcnow()
|
startTime = datetime.utcnow()
|
||||||
|
@ -160,7 +163,7 @@ class MatrixModule:
|
||||||
return events_result.get('items', [])
|
return events_result.get('items', [])
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Google calendar. Lists 10 next events by default. today = list today\'s events.')
|
return ('Google calendar. Lists 10 next events by default. today = list today\'s events.')
|
||||||
|
|
||||||
def get_settings(self):
|
def get_settings(self):
|
||||||
return {'calendar_rooms': self.calendar_rooms}
|
return {'calendar_rooms': self.calendar_rooms}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
class MatrixModule:
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
async def matrix_message(self, bot, room, event):
|
async def matrix_message(self, bot, room, event):
|
||||||
msg = f'This is Hemppa {bot.version}, a generic Matrix bot. Known commands:\n\n'
|
msg = f'This is Hemppa {bot.version}, a generic Matrix bot. Known commands:\n\n'
|
||||||
|
|
||||||
|
@ -13,4 +16,4 @@ class MatrixModule:
|
||||||
await bot.send_text(room, msg)
|
await bot.send_text(room, msg)
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Prints help on commands')
|
return 'Prints help on commands'
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import traceback
|
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from modules.common.pollingservice import PollingService
|
|
||||||
|
|
||||||
from igramscraper.exception.instagram_not_found_exception import \
|
from igramscraper.exception.instagram_not_found_exception import \
|
||||||
InstagramNotFoundException
|
InstagramNotFoundException
|
||||||
from igramscraper.instagram import Instagram
|
from igramscraper.instagram import Instagram
|
||||||
|
|
||||||
|
from modules.common.pollingservice import PollingService
|
||||||
|
|
||||||
|
|
||||||
class MatrixModule(PollingService):
|
class MatrixModule(PollingService):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -21,12 +23,14 @@ class MatrixModule(PollingService):
|
||||||
for media in medias:
|
for media in medias:
|
||||||
if send_messages:
|
if send_messages:
|
||||||
if media.identifier not in self.known_ids:
|
if media.identifier not in self.known_ids:
|
||||||
await bot.send_html(bot.get_room_by_id(roomid), f'<a href="{media.link}">Instagram {account}:</a> {media.caption}', f'{account}: {media.caption} {media.link}')
|
await bot.send_html(bot.get_room_by_id(roomid),
|
||||||
|
f'<a href="{media.link}">Instagram {account}:</a> {media.caption}',
|
||||||
|
f'{account}: {media.caption} {media.link}')
|
||||||
self.known_ids.add(media.identifier)
|
self.known_ids.add(media.identifier)
|
||||||
|
|
||||||
except InstagramNotFoundException:
|
except InstagramNotFoundException:
|
||||||
print('ig error: there is ', account,
|
print('ig error: there is ', account,
|
||||||
' account that does not exist - deleting from room')
|
' account that does not exist - deleting from room')
|
||||||
self.account_rooms[roomid].remove(account)
|
self.account_rooms[roomid].remove(account)
|
||||||
bot.save_settings()
|
bot.save_settings()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from geopy.geocoders import Nominatim
|
from geopy.geocoders import Nominatim
|
||||||
from nio import RoomMessageUnknown
|
from nio import RoomMessageUnknown
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
class MatrixModule:
|
class MatrixModule(BotModule):
|
||||||
bot = None
|
bot = None
|
||||||
|
|
||||||
def matrix_start(self, bot):
|
def matrix_start(self, bot):
|
||||||
|
@ -29,7 +30,7 @@ class MatrixModule:
|
||||||
float(latlon[1])
|
float(latlon[1])
|
||||||
|
|
||||||
osm_link = 'https://www.openstreetmap.org/?mlat=' + \
|
osm_link = 'https://www.openstreetmap.org/?mlat=' + \
|
||||||
latlon[0] + "&mlon=" + latlon[1]
|
latlon[0] + "&mlon=" + latlon[1]
|
||||||
|
|
||||||
plain = sender + ' 🚩 ' + osm_link
|
plain = sender + ' 🚩 ' + osm_link
|
||||||
html = f'{sender} 🚩 <a href={osm_link}>{location_text}</a>'
|
html = f'{sender} 🚩 <a href={osm_link}>{location_text}</a>'
|
||||||
|
@ -58,4 +59,4 @@ class MatrixModule:
|
||||||
await bot.send_text(room, "Can't find " + query + " on map!")
|
await bot.send_text(room, "Can't find " + query + " on map!")
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Search for locations and display Matrix location events as OSM links')
|
return 'Search for locations and display Matrix location events as OSM links'
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
class MatrixModule:
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
async def matrix_message(self, bot, room, event):
|
async def matrix_message(self, bot, room, event):
|
||||||
args = event.body.split()
|
args = event.body.split()
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
icao = args[1]
|
icao = args[1]
|
||||||
metar_url = "https://tgftp.nws.noaa.gov/data/observations/metar/stations/" + \
|
metar_url = "https://tgftp.nws.noaa.gov/data/observations/metar/stations/" + \
|
||||||
icao.upper() + ".TXT"
|
icao.upper() + ".TXT"
|
||||||
response = urllib.request.urlopen(metar_url)
|
response = urllib.request.urlopen(metar_url)
|
||||||
lines = response.readlines()
|
lines = response.readlines()
|
||||||
await bot.send_text(room, lines[1].decode("utf-8").strip())
|
await bot.send_text(room, lines[1].decode("utf-8").strip())
|
||||||
|
@ -15,4 +17,4 @@ class MatrixModule:
|
||||||
await bot.send_text(room, 'Usage: !metar <icao code>')
|
await bot.send_text(room, 'Usage: !metar <icao code>')
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Metar data access (usage: !metar <icao code>)')
|
return ('Metar data access (usage: !metar <icao code>)')
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import urllib.request
|
|
||||||
import re
|
import re
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
class MatrixModule:
|
class MatrixModule(BotModule):
|
||||||
async def matrix_message(self, bot, room, event):
|
async def matrix_message(self, bot, room, event):
|
||||||
args = event.body.split()
|
args = event.body.split()
|
||||||
if len(args) == 2 and len(args[1]) == 4:
|
if len(args) == 2 and len(args[1]) == 4:
|
||||||
|
@ -13,12 +15,12 @@ class MatrixModule:
|
||||||
await bot.send_text(room, 'Usage: !notam <icao code>')
|
await bot.send_text(room, 'Usage: !notam <icao code>')
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('NOTAM data access (usage: !notam <icao code>) - Currently Finnish airports only')
|
return ('NOTAM data access (usage: !notam <icao code>) - Currently Finnish airports only')
|
||||||
|
|
||||||
# TODO: This handles only finnish airports. Implement support for other countries.
|
# TODO: This handles only finnish airports. Implement support for other countries.
|
||||||
def get_notam(self, icao):
|
def get_notam(self, icao):
|
||||||
if not icao.startswith('EF'):
|
if not icao.startswith('EF'):
|
||||||
return('Only Finnish airports supported currently, sorry.')
|
return ('Only Finnish airports supported currently, sorry.')
|
||||||
|
|
||||||
icao_first_letter = icao[2]
|
icao_first_letter = icao[2]
|
||||||
if icao_first_letter < 'M':
|
if icao_first_letter < 'M':
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
class MatrixModule:
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
async def matrix_message(self, bot, room, event):
|
async def matrix_message(self, bot, room, event):
|
||||||
args = event.body.split()
|
args = event.body.split()
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
|
@ -18,4 +20,4 @@ class MatrixModule:
|
||||||
await bot.send_text(room, 'Usage: !taf <icao code>')
|
await bot.send_text(room, 'Usage: !taf <icao code>')
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Taf data access (usage: !taf <icao code>)')
|
return ('Taf data access (usage: !taf <icao code>)')
|
||||||
|
|
|
@ -3,12 +3,14 @@ from datetime import datetime
|
||||||
|
|
||||||
from pyteamup import Calendar
|
from pyteamup import Calendar
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# TeamUp calendar notifications
|
# TeamUp calendar notifications
|
||||||
#
|
#
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
|
|
||||||
class MatrixModule:
|
class MatrixModule(BotModule):
|
||||||
api_key = None
|
api_key = None
|
||||||
calendar_rooms = dict() # Roomid -> [calid, calid..]
|
calendar_rooms = dict() # Roomid -> [calid, calid..]
|
||||||
calendars = dict() # calid -> Calendar
|
calendars = dict() # calid -> Calendar
|
||||||
|
@ -87,7 +89,7 @@ class MatrixModule:
|
||||||
await bot.send_text(room, 'Api key set')
|
await bot.send_text(room, 'Api key set')
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return('Polls teamup calendar.')
|
return ('Polls teamup calendar.')
|
||||||
|
|
||||||
async def poll_all_calendars(self, bot):
|
async def poll_all_calendars(self, bot):
|
||||||
delete_rooms = []
|
delete_rooms = []
|
||||||
|
@ -102,7 +104,7 @@ class MatrixModule:
|
||||||
await bot.send_text(bot.get_room_by_id(roomid), 'Calendar: ' + self.eventToString(event))
|
await bot.send_text(bot.get_room_by_id(roomid), 'Calendar: ' + self.eventToString(event))
|
||||||
else:
|
else:
|
||||||
delete_rooms.append(roomid)
|
delete_rooms.append(roomid)
|
||||||
|
|
||||||
for roomid in delete_rooms:
|
for roomid in delete_rooms:
|
||||||
self.calendar_rooms.pop(roomid, None)
|
self.calendar_rooms.pop(roomid, None)
|
||||||
|
|
||||||
|
@ -115,7 +117,7 @@ class MatrixModule:
|
||||||
return datetime.strptime(dts, '%Y-%m-%dT%H:%M:%S')
|
return datetime.strptime(dts, '%Y-%m-%dT%H:%M:%S')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pos = len(dts) - 3
|
pos = len(dts) - 3
|
||||||
dts = dts[:pos] + dts[pos+1:]
|
dts = dts[:pos] + dts[pos + 1:]
|
||||||
return datetime.strptime(dts, '%Y-%m-%dT%H:%M:%S%z')
|
return datetime.strptime(dts, '%Y-%m-%dT%H:%M:%S%z')
|
||||||
|
|
||||||
def eventToString(self, event):
|
def eventToString(self, event):
|
||||||
|
@ -123,7 +125,7 @@ class MatrixModule:
|
||||||
if len(event['title']) == 0:
|
if len(event['title']) == 0:
|
||||||
event['title'] = '(empty name)'
|
event['title'] = '(empty name)'
|
||||||
|
|
||||||
if(event['delete_dt']):
|
if (event['delete_dt']):
|
||||||
s = event['title'] + ' deleted.'
|
s = event['title'] + ' deleted.'
|
||||||
else:
|
else:
|
||||||
s = event['title'] + " " + (event['notes'] or '') + \
|
s = event['title'] + " " + (event['notes'] or '') + \
|
||||||
|
@ -144,7 +146,7 @@ class MatrixModule:
|
||||||
self.calendars[calid].timestamp = int(time.time())
|
self.calendars[calid].timestamp = int(time.time())
|
||||||
|
|
||||||
def get_settings(self):
|
def get_settings(self):
|
||||||
return {'apikey': self.api_key or '', 'calendar_rooms': self.calendar_rooms}
|
return {'apikey': self.api_key or '', 'calendar_rooms': self.calendar_rooms}
|
||||||
|
|
||||||
def set_settings(self, data):
|
def set_settings(self, data):
|
||||||
if data.get('calendar_rooms'):
|
if data.get('calendar_rooms'):
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from twitterscraper import query_tweets_from_user
|
from twitterscraper import query_tweets_from_user
|
||||||
|
|
||||||
from modules.common.pollingservice import PollingService
|
from modules.common.pollingservice import PollingService
|
||||||
|
|
||||||
|
|
||||||
# https://github.com/taspinar/twitterscraper/tree/master/twitterscraper
|
# https://github.com/taspinar/twitterscraper/tree/master/twitterscraper
|
||||||
|
|
||||||
class MatrixModule(PollingService):
|
class MatrixModule(PollingService):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.service_name = 'Twitter'
|
self.service_name = 'Twitter'
|
||||||
|
@ -15,7 +17,9 @@ class MatrixModule(PollingService):
|
||||||
for tweet in tweets:
|
for tweet in tweets:
|
||||||
if tweet.tweet_id not in self.known_ids:
|
if tweet.tweet_id not in self.known_ids:
|
||||||
if send_messages:
|
if send_messages:
|
||||||
await bot.send_html(bot.get_room_by_id(roomid), f'<a href="https://twitter.com{tweet.tweet_url}">Twitter {account}</a>: {tweet.text}', f'Twitter {account}: {tweet.text} - https://twitter.com{tweet.tweet_url}')
|
await bot.send_html(bot.get_room_by_id(roomid),
|
||||||
|
f'<a href="https://twitter.com{tweet.tweet_url}">Twitter {account}</a>: {tweet.text}',
|
||||||
|
f'Twitter {account}: {tweet.text} - https://twitter.com{tweet.tweet_url}')
|
||||||
self.known_ids.add(tweet.tweet_id)
|
self.known_ids.add(tweet.tweet_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
print('Polling twitter account failed:')
|
print('Polling twitter account failed:')
|
||||||
|
|
|
@ -6,8 +6,10 @@ import httpx
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from nio import RoomMessageText
|
from nio import RoomMessageText
|
||||||
|
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
|
||||||
class MatrixModule:
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
"""
|
"""
|
||||||
Simple url fetch and spit out title module.
|
Simple url fetch and spit out title module.
|
||||||
|
|
||||||
|
@ -152,3 +154,7 @@ class MatrixModule:
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
return "If I see a url in a message I will try to get the title from the page and spit it out"
|
return "If I see a url in a message I will try to get the title from the page and spit it out"
|
||||||
|
|
||||||
|
def dump(self, obj):
|
||||||
|
for attr in dir(obj):
|
||||||
|
print("obj.%s = %r" % (attr, getattr(obj, attr)))
|
Loading…
Reference in New Issue