commit
325e1e623c
|
@ -1,3 +1,9 @@
|
|||
# editors
|
||||
.vscode
|
||||
|
||||
# ignore Pipfile.lock
|
||||
Pipfile.lock
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
|
3
Pipfile
3
Pipfile
|
@ -16,6 +16,9 @@ igramscraper = "*"
|
|||
|
||||
[dev-packages]
|
||||
pylint = "*"
|
||||
pycodestyle = "*"
|
||||
flake8 = "*"
|
||||
autopep8 = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.7"
|
||||
|
|
56
bot.py
56
bot.py
|
@ -1,25 +1,29 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import json
|
||||
import glob
|
||||
import traceback
|
||||
import importlib
|
||||
import sys
|
||||
import re
|
||||
import requests
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
import urllib.parse
|
||||
from nio import (AsyncClient, RoomMessageText, RoomMessageUnknown, JoinError, InviteEvent)
|
||||
|
||||
import requests
|
||||
from nio import AsyncClient, InviteEvent, JoinError, RoomMessageText
|
||||
|
||||
# Couple of custom exceptions
|
||||
|
||||
|
||||
class CommandRequiresAdmin(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CommandRequiresOwner(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Bot:
|
||||
appid = 'org.vranki.hemppa'
|
||||
version = '1.1'
|
||||
|
@ -59,11 +63,12 @@ class Bot:
|
|||
if not self.is_owner(event):
|
||||
raise CommandRequiresOwner
|
||||
|
||||
# Returns true if event's sender is admin in the room event was sent in, or is bot owner
|
||||
# Returns true if event's sender is admin in the room event was sent in,
|
||||
# or is bot owner
|
||||
def is_admin(self, room, event):
|
||||
if self.is_owner(event):
|
||||
return True
|
||||
if not event.sender in room.power_levels.users:
|
||||
if event.sender not in room.power_levels.users:
|
||||
return False
|
||||
return room.power_levels.users[event.sender] >= 50
|
||||
|
||||
|
@ -77,9 +82,9 @@ class Bot:
|
|||
if "get_settings" in dir(moduleobject):
|
||||
try:
|
||||
module_settings[modulename] = moduleobject.get_settings()
|
||||
except:
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
data = { self.appid: self.version, 'module_settings': module_settings}
|
||||
data = {self.appid: self.version, 'module_settings': module_settings}
|
||||
self.set_account_data(data)
|
||||
|
||||
def load_settings(self, data):
|
||||
|
@ -91,8 +96,9 @@ class Bot:
|
|||
if data['module_settings'].get(modulename):
|
||||
if "set_settings" in dir(moduleobject):
|
||||
try:
|
||||
moduleobject.set_settings(data['module_settings'][modulename])
|
||||
except:
|
||||
moduleobject.set_settings(
|
||||
data['module_settings'][modulename])
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
async def message_cb(self, room, event):
|
||||
|
@ -114,7 +120,7 @@ class Bot:
|
|||
await self.send_text(room, f'Sorry, you need admin power level in this room to run that command.')
|
||||
except CommandRequiresOwner:
|
||||
await self.send_text(room, f'Sorry, only bot owner can run that command.')
|
||||
except:
|
||||
except Exception:
|
||||
await self.send_text(room, f'Module {command} experienced difficulty: {sys.exc_info()[0]} - see log for details')
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
|
@ -124,12 +130,13 @@ class Bot:
|
|||
result = await self.client.join(room.room_id)
|
||||
if type(result) == JoinError:
|
||||
print(f"Error joining room {room.room_id} (attempt %d): %s",
|
||||
attempt, result.message,
|
||||
)
|
||||
attempt, result.message,
|
||||
)
|
||||
else:
|
||||
break
|
||||
else:
|
||||
print(f'Received invite event, but not joining as sender is not owner or bot not configured to join on invite. {event}')
|
||||
print(
|
||||
f'Received invite event, but not joining as sender is not owner or bot not configured to join on invite. {event}')
|
||||
|
||||
def load_module(self, modulename):
|
||||
try:
|
||||
|
@ -157,7 +164,7 @@ class Bot:
|
|||
if "matrix_poll" in dir(moduleobject):
|
||||
try:
|
||||
await moduleobject.matrix_poll(bot, self.pollcount)
|
||||
except:
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
await asyncio.sleep(10)
|
||||
|
||||
|
@ -178,11 +185,13 @@ class Bot:
|
|||
response = requests.get(ad_url)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
print(f'Getting account data failed: {response} {response.json()} - this is normal if you have not saved any settings yet.')
|
||||
print(
|
||||
f'Getting account data failed: {response} {response.json()} - this is normal if you have not saved any settings yet.')
|
||||
return None
|
||||
|
||||
def init(self):
|
||||
self.client = AsyncClient(os.environ['MATRIX_SERVER'], os.environ['MATRIX_USER'])
|
||||
self.client = AsyncClient(
|
||||
os.environ['MATRIX_SERVER'], os.environ['MATRIX_USER'])
|
||||
self.client.access_token = os.getenv('MATRIX_ACCESS_TOKEN')
|
||||
self.join_on_invite = os.getenv("JOIN_ON_INVITE") is not None
|
||||
self.owners = os.environ['BOT_OWNERS'].split(',')
|
||||
|
@ -195,13 +204,14 @@ class Bot:
|
|||
if "matrix_stop" in dir(moduleobject):
|
||||
try:
|
||||
moduleobject.matrix_stop(bot)
|
||||
except:
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
async def run(self):
|
||||
if not self.client.access_token:
|
||||
await self.client.login(os.environ['MATRIX_PASSWORD'])
|
||||
print("Logged in with password, access token:", self.client.access_token)
|
||||
print("Logged in with password, access token:",
|
||||
self.client.access_token)
|
||||
|
||||
await self.client.sync()
|
||||
|
||||
|
@ -211,7 +221,7 @@ class Bot:
|
|||
if "matrix_start" in dir(moduleobject):
|
||||
try:
|
||||
moduleobject.matrix_start(bot)
|
||||
except:
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
self.poll_task = asyncio.get_event_loop().create_task(self.poll_timer())
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import shlex
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
daily_commands = dict() # room_id -> command json
|
||||
daily_commands = dict() # room_id -> command json
|
||||
last_hour = datetime.now().hour
|
||||
|
||||
async def matrix_message(self, bot, room, event):
|
||||
|
@ -16,7 +17,8 @@ class MatrixModule:
|
|||
dailycmd = args[2]
|
||||
if not self.daily_commands.get(room.room_id):
|
||||
self.daily_commands[room.room_id] = []
|
||||
self.daily_commands[room.room_id].append({ 'time': dailytime, 'command': dailycmd })
|
||||
self.daily_commands[room.room_id].append(
|
||||
{'time': dailytime, 'command': dailycmd})
|
||||
bot.save_settings()
|
||||
await bot.send_text(room, 'Daily command added.')
|
||||
elif len(args) == 1:
|
||||
|
@ -31,7 +33,7 @@ class MatrixModule:
|
|||
return('Runs scheduled commands')
|
||||
|
||||
def get_settings(self):
|
||||
return { 'daily_commands': self.daily_commands }
|
||||
return {'daily_commands': self.daily_commands}
|
||||
|
||||
def set_settings(self, data):
|
||||
if data.get('daily_commands'):
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
from __future__ import print_function
|
||||
from datetime import datetime
|
||||
import datetime
|
||||
import pickle
|
||||
import os.path
|
||||
import time
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import pickle
|
||||
from datetime import datetime
|
||||
|
||||
from googleapiclient.discovery import build
|
||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
from google.auth.transport.requests import Request
|
||||
|
||||
|
||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
from googleapiclient.discovery import build
|
||||
|
||||
#
|
||||
# Google calendar notifications
|
||||
|
@ -20,18 +17,19 @@ from google.auth.transport.requests import Request
|
|||
# can be copied to another computer.
|
||||
#
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
def matrix_start(self, bot):
|
||||
self.bot = bot
|
||||
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
||||
self.credentials_file = "credentials.json"
|
||||
self.service = None
|
||||
self.calendar_rooms = dict() # Contains room_id -> [calid, calid] ..
|
||||
self.calendar_rooms = dict() # Contains room_id -> [calid, calid] ..
|
||||
|
||||
creds = None
|
||||
|
||||
if not os.path.exists(self.credentials_file) or os.path.getsize(self.credentials_file) == 0:
|
||||
return # No-op if not set up
|
||||
return # No-op if not set up
|
||||
|
||||
if os.path.exists('token.pickle'):
|
||||
with open('token.pickle', 'rb') as token:
|
||||
|
@ -45,7 +43,8 @@ class MatrixModule:
|
|||
else:
|
||||
flow = InstalledAppFlow.from_client_secrets_file(
|
||||
self.credentials_file, self.SCOPES)
|
||||
creds = flow.run_local_server(port=0) # urn:ietf:wg:oauth:2.0:oob
|
||||
# urn:ietf:wg:oauth:2.0:oob
|
||||
creds = flow.run_local_server(port=0)
|
||||
# Save the credentials for the next run
|
||||
with open('token.pickle', 'wb') as token:
|
||||
pickle.dump(creds, token)
|
||||
|
@ -54,14 +53,15 @@ class MatrixModule:
|
|||
self.service = build('calendar', 'v3', credentials=creds)
|
||||
|
||||
try:
|
||||
calendar_list = self.service.calendarList().list().execute()['items']
|
||||
print(f'Google calendar set up successfully with access to {len(calendar_list)} calendars:\n')
|
||||
calendar_list = self.service.calendarList().list().execute()[
|
||||
'items']
|
||||
print(
|
||||
f'Google calendar set up successfully with access to {len(calendar_list)} calendars:\n')
|
||||
for calendar in calendar_list:
|
||||
print(calendar['summary'] + ' - ' + calendar['id'])
|
||||
except:
|
||||
except Exception:
|
||||
print('Getting calendar list failed!')
|
||||
|
||||
|
||||
async def matrix_message(self, bot, room, event):
|
||||
if not self.service:
|
||||
await bot.send_text(room, 'Google calendar not set up for this bot.')
|
||||
|
@ -95,7 +95,8 @@ class MatrixModule:
|
|||
else:
|
||||
self.calendar_rooms[room.room_id] = [calid]
|
||||
|
||||
print(f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
print(
|
||||
f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
|
||||
bot.save_settings()
|
||||
|
||||
|
@ -111,7 +112,8 @@ class MatrixModule:
|
|||
if self.calendar_rooms.get(room.room_id):
|
||||
self.calendar_rooms[room.room_id].remove(calid)
|
||||
|
||||
print(f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
print(
|
||||
f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
|
||||
bot.save_settings()
|
||||
|
||||
|
@ -141,28 +143,29 @@ class MatrixModule:
|
|||
startTime = datetime.datetime.utcnow()
|
||||
now = startTime.isoformat() + 'Z'
|
||||
events_result = self.service.events().list(calendarId=calid, timeMin=now,
|
||||
maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
events = events_result.get('items', [])
|
||||
return events
|
||||
|
||||
def list_today(self, calid):
|
||||
startTime = datetime.datetime.utcnow()
|
||||
startTime = startTime.replace(hour = 0, minute = 0, second = 0, microsecond=0)
|
||||
startTime = startTime.replace(
|
||||
hour=0, minute=0, second=0, microsecond=0)
|
||||
endTime = startTime + datetime.timedelta(hours=24)
|
||||
now = startTime.isoformat() + 'Z'
|
||||
end = endTime.isoformat() + 'Z'
|
||||
print('Looking for events between', now, end)
|
||||
events_result = self.service.events().list(calendarId=calid, timeMin=now,
|
||||
timeMax=end, maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
timeMax=end, maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
return events_result.get('items', [])
|
||||
|
||||
def help(self):
|
||||
return('Google calendar. Lists 10 next events by default. today = list today\'s events.')
|
||||
|
||||
def get_settings(self):
|
||||
return { 'calendar_rooms': self.calendar_rooms }
|
||||
return {'calendar_rooms': self.calendar_rooms}
|
||||
|
||||
def set_settings(self, data):
|
||||
if data.get('calendar_rooms'):
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
from igramscraper.instagram import Instagram
|
||||
from igramscraper.exception.instagram_not_found_exception import InstagramNotFoundException
|
||||
from datetime import datetime, timedelta
|
||||
from random import randrange
|
||||
|
||||
from igramscraper.exception.instagram_not_found_exception import \
|
||||
InstagramNotFoundException
|
||||
from igramscraper.instagram import Instagram
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
instagram = Instagram()
|
||||
|
||||
known_ids = set()
|
||||
account_rooms = dict() # Roomid -> [account, account..]
|
||||
next_poll_time = dict() # Roomid -> datetime, None = not polled yet
|
||||
account_rooms = dict() # Roomid -> [account, account..]
|
||||
next_poll_time = dict() # Roomid -> datetime, None = not polled yet
|
||||
|
||||
async def matrix_poll(self, bot, pollcount):
|
||||
if len(self.account_rooms):
|
||||
|
@ -27,7 +30,8 @@ class MatrixModule:
|
|||
try:
|
||||
await self.poll_account(bot, account, roomid, send_messages)
|
||||
except InstagramNotFoundException:
|
||||
print('ig error: there is ', account, ' account that does not exist - deleting from room')
|
||||
print('ig error: there is ', account,
|
||||
' account that does not exist - deleting from room')
|
||||
self.account_rooms[roomid].remove(account)
|
||||
bot.save_settings()
|
||||
|
||||
|
@ -77,7 +81,8 @@ class MatrixModule:
|
|||
else:
|
||||
self.account_rooms[room.room_id] = [account]
|
||||
|
||||
print(f'Accounts now for this room {self.account_rooms.get(room.room_id)}')
|
||||
print(
|
||||
f'Accounts now for this room {self.account_rooms.get(room.room_id)}')
|
||||
|
||||
try:
|
||||
await self.poll_account(bot, account, room.room_id, False)
|
||||
|
@ -91,18 +96,20 @@ class MatrixModule:
|
|||
bot.must_be_admin(room, event)
|
||||
|
||||
account = args[2]
|
||||
print(f'Removing account {account} from room id {room.room_id}')
|
||||
print(
|
||||
f'Removing account {account} from room id {room.room_id}')
|
||||
|
||||
if self.account_rooms.get(room.room_id):
|
||||
self.account_rooms[room.room_id].remove(account)
|
||||
|
||||
print(f'Accounts now for this room {self.account_rooms.get(room.room_id)}')
|
||||
print(
|
||||
f'Accounts now for this room {self.account_rooms.get(room.room_id)}')
|
||||
|
||||
bot.save_settings()
|
||||
await bot.send_text(room, 'Removed instagram account from this room')
|
||||
|
||||
def get_settings(self):
|
||||
return { 'account_rooms': self.account_rooms }
|
||||
return {'account_rooms': self.account_rooms}
|
||||
|
||||
def set_settings(self, data):
|
||||
if data.get('account_rooms'):
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from geopy.geocoders import Nominatim
|
||||
from nio import (RoomMessageUnknown)
|
||||
from nio import RoomMessageUnknown
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
bot = None
|
||||
|
||||
def matrix_start(self, bot):
|
||||
self.bot = bot
|
||||
bot.client.add_event_callback(self.unknown_cb, RoomMessageUnknown)
|
||||
|
@ -26,7 +28,8 @@ class MatrixModule:
|
|||
float(latlon[0])
|
||||
float(latlon[1])
|
||||
|
||||
osm_link = 'https://www.openstreetmap.org/?mlat=' + latlon[0] + "&mlon=" + latlon[1]
|
||||
osm_link = 'https://www.openstreetmap.org/?mlat=' + \
|
||||
latlon[0] + "&mlon=" + latlon[1]
|
||||
|
||||
plain = sender + ' 🚩 ' + osm_link
|
||||
html = f'{sender} 🚩 <a href={osm_link}>{location_text}</a>'
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import subprocess
|
||||
import os
|
||||
import urllib.request
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
async def matrix_message(self, bot, room, event):
|
||||
args = event.body.split()
|
||||
if len(args) == 2:
|
||||
icao = args[1]
|
||||
metar_url = "https://tgftp.nws.noaa.gov/data/observations/metar/stations/" + icao.upper() + ".TXT"
|
||||
metar_url = "https://tgftp.nws.noaa.gov/data/observations/metar/stations/" + \
|
||||
icao.upper() + ".TXT"
|
||||
response = urllib.request.urlopen(metar_url)
|
||||
lines = response.readlines()
|
||||
await bot.send_text(room, lines[1].decode("utf-8").strip())
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
import urllib.request
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
async def matrix_message(self, bot, room, event):
|
||||
args = event.body.split()
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
from pyteamup import Calendar, Event
|
||||
from datetime import datetime
|
||||
import time
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from pyteamup import Calendar
|
||||
|
||||
#
|
||||
# TeamUp calendar notifications
|
||||
#
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
api_key = None
|
||||
calendar_rooms = dict() # Roomid -> [calid, calid..]
|
||||
calendars = dict() # calid -> Calendar
|
||||
calendar_rooms = dict() # Roomid -> [calid, calid..]
|
||||
calendars = dict() # calid -> Calendar
|
||||
|
||||
async def matrix_poll(self, bot, pollcount):
|
||||
if self.api_key:
|
||||
if pollcount % (6 * 5) == 0: # Poll every 5 min
|
||||
await self.poll_all_calendars(bot)
|
||||
if pollcount % (6 * 5) == 0: # Poll every 5 min
|
||||
await self.poll_all_calendars(bot)
|
||||
|
||||
async def matrix_message(self, bot, room, event):
|
||||
args = event.body.split()
|
||||
|
@ -24,10 +26,14 @@ class MatrixModule:
|
|||
calendar = self.calendars[calendarid]
|
||||
events = calendar.get_event_collection()
|
||||
for event in events:
|
||||
s = '<b>' + str(event.start_dt.day) + '.' + str(event.start_dt.month)
|
||||
s = '<b>' + str(event.start_dt.day) + \
|
||||
'.' + str(event.start_dt.month)
|
||||
if not event.all_day:
|
||||
s = s + ' ' + event.start_dt.strftime("%H:%M") + ' (' + str(event.duration) + ' min)'
|
||||
s = s + '</b> ' + event.title + " " + (event.notes or '')
|
||||
s = s + ' ' + \
|
||||
event.start_dt.strftime(
|
||||
"%H:%M") + ' (' + str(event.duration) + ' min)'
|
||||
s = s + '</b> ' + event.title + \
|
||||
" " + (event.notes or '')
|
||||
await bot.send_html(room, s, s)
|
||||
elif len(args) == 2:
|
||||
if args[1] == 'list':
|
||||
|
@ -51,7 +57,8 @@ class MatrixModule:
|
|||
else:
|
||||
self.calendar_rooms[room.room_id] = [calid]
|
||||
|
||||
print(f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
print(
|
||||
f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
|
||||
bot.save_settings()
|
||||
self.setup_calendars()
|
||||
|
@ -65,7 +72,8 @@ class MatrixModule:
|
|||
if self.calendar_rooms.get(room.room_id):
|
||||
self.calendar_rooms[room.room_id].remove(calid)
|
||||
|
||||
print(f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
print(
|
||||
f'Calendars now for this room {self.calendar_rooms.get(room.room_id)}')
|
||||
|
||||
bot.save_settings()
|
||||
self.setup_calendars()
|
||||
|
@ -85,12 +93,12 @@ class MatrixModule:
|
|||
for roomid in self.calendar_rooms:
|
||||
calendars = self.calendar_rooms[roomid]
|
||||
for calendarid in calendars:
|
||||
events, timestamp = self.poll_server(self.calendars[calendarid])
|
||||
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))
|
||||
|
||||
|
||||
def poll_server(self, calendar):
|
||||
events, timestamp = calendar.get_changed_events(calendar.timestamp)
|
||||
return events, timestamp
|
||||
|
@ -111,9 +119,12 @@ class MatrixModule:
|
|||
if(event['delete_dt']):
|
||||
s = event['title'] + ' deleted.'
|
||||
else:
|
||||
s = event['title'] + " " + (event['notes'] or '') + ' ' + str(startdt.day) + '.' + str(startdt.month)
|
||||
s = event['title'] + " " + (event['notes'] or '') + \
|
||||
' ' + str(startdt.day) + '.' + str(startdt.month)
|
||||
if not event['all_day']:
|
||||
s = s + ' ' + startdt.strftime("%H:%M") + ' (' + str(event['duration']) + ' min)'
|
||||
s = s + ' ' + \
|
||||
startdt.strftime("%H:%M") + \
|
||||
' (' + str(event['duration']) + ' min)'
|
||||
return s
|
||||
|
||||
def setup_calendars(self):
|
||||
|
@ -126,13 +137,13 @@ class MatrixModule:
|
|||
self.calendars[calid].timestamp = int(time.time())
|
||||
|
||||
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):
|
||||
if data.get('calendar_rooms'):
|
||||
self.calendar_rooms = data['calendar_rooms']
|
||||
if data.get('apikey'):
|
||||
self.api_key = data['apikey']
|
||||
if self.api_key and len(self.api_key)==0:
|
||||
if self.api_key and len(self.api_key) == 0:
|
||||
self.api_key = None
|
||||
self.setup_calendars()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import time
|
||||
|
||||
|
||||
class MatrixModule:
|
||||
def matrix_start(self, bot):
|
||||
self.starttime = time.time()
|
||||
|
|
Loading…
Reference in New Issue