def calc_boundaries(direction): sheet_m = int( xbmcgui.Window(10000).getProperty('calendar_month')) + direction sheet_y = int(xbmcgui.Window(10000).getProperty('calendar_year')) if sheet_m < 1: sheet_m = 12 sheet_y -= 1 elif sheet_m > 12: sheet_m = 1 sheet_y += 1 if sheet_y == datetime.today().year: if sheet_m < datetime.today().month or sheet_m > datetime.today( ).month + tools.getAddonSetting('timemax', sType=tools.NUM): tools.writeLog('prev/next month outside boundary') return else: if sheet_m + 12 > datetime.today().month + tools.getAddonSetting( 'timemax', sType=tools.NUM): tools.writeLog('prev/next month outside boundary') return xbmcgui.Window(10000).setProperty('calendar_month', str(sheet_m)) xbmcgui.Window(10000).setProperty('calendar_year', str(sheet_y)) _header = '%s %s' % (__LS__(30119 + sheet_m), sheet_y) xbmcgui.Window(10000).setProperty('calendar_header', _header)
def get_calendarIdFromSetup(self, setting): calId = [] _cals = t.getAddonSetting(setting).split(', ') if len(_cals) == 1 and _cals[0] == 'primary': calId.append('primary') else: cals = self.get_calendars() for cal in cals: if cal.get('summaryOverride', cal.get('summary', 'primary')) in _cals: calId.append(cal.get('id')) t.writeLog('getting cal ids from setup: %s' % (', '.join(calId))) return calId
def controller(mode=None, handle=None, content=None, eventId=None, actor=None): now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0).isoformat() + 'Z' timemax = ( datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) + relativedelta.relativedelta(months=tools.getAddonSetting( 'timemax', sType=tools.NUM))).isoformat() + 'Z' if mode == 'load_glotz_key': glotz_apikey = tools.dialogFile(__LS__(30089)) if glotz_apikey != '': tools.setAddonSetting('glotz_apikey', glotz_apikey) tools.writeLog('API key for glotz.info successfull stored') tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'abort_reminders': tools.writeLog('abort notification service by setup', xbmc.LOGNOTICE) xbmcgui.Window(10000).setProperty('reminders', '0') elif mode == 'getcontent': googlecal = Calendar() googlecal.build_sheet(handle, TEMP_STORAGE_EVENTS, content, now, timemax, maxResult=30) elif mode == 'getinfo' and eventId != '': googlecal = Calendar() events = eventId.strip(' ').split(' ') _header = '' _msg = '' for event in events: _ev = googlecal.get_event(event, TEMP_STORAGE_EVENTS) _mev = googlecal.prepareForAddon(_ev, optTimeStamps=True) _time = '' if _mev.get( 'range', '') == '' else '[B]%s[/B]: ' % (_mev.get('range')) if actor and actor == 'eventlist': _header = 'S%02iE%02i: %s' % ( _mev.get('season'), _mev.get('episode'), _mev.get('title')) _msg = '%s' % (_mev.get('plot')) else: _header = '%s %s %s' % (__LS__(30109), __LS__(30145), _mev.get('shortdate', '')) _msg += '%s%s[CR]%s[CR][CR]' % (_time, _mev.get( 'summary', ''), _mev.get('description') or __LS__(30093)) tools.dialogOK(_header, _msg) elif mode == 'prev': calc_boundaries(-1) elif mode == 'next': calc_boundaries(1) # this is the real controller bootstrap elif mode == 'gui': try: Popup = xbmcgui.WindowXMLDialog(__xml__, __path__) Popup.doModal() del Popup except RuntimeError as e: raise FileNotFoundException('%s: %s' % (e.message, __xml__)) else: pass
__addon__ = xbmcaddon.Addon() __path__ = __addon__.getAddonInfo('path') __icon__ = os.path.join(xbmc.translatePath(__path__), 'resources', 'skins', 'Default', 'media', 'icon.png') __icon2__ = os.path.join(xbmc.translatePath(__path__), 'resources', 'skins', 'Default', 'media', 'icon_alert.png') __profiles__ = __addon__.getAddonInfo('profile') __LS__ = __addon__.getLocalizedString TEMP_STORAGE_CALENDARS = os.path.join(xbmc.translatePath(__profiles__), 'calendars.json') TEMP_STORAGE_NOTIFICATIONS = os.path.join(xbmc.translatePath(__profiles__), 'notifications.json') if t.getAddonSetting('show_onstart', sType=t.BOOL): xbmcgui.Window(10000).setProperty('reminders', '1') else: xbmcgui.Window(10000).setProperty('reminders', '0') _cycle = 0 try: googlecal = Calendar() while xbmcgui.Window(10000).getProperty('reminders') == '1': now = datetime.utcnow().isoformat() + 'Z' timemax = (datetime.utcnow() + relativedelta.relativedelta( months=t.getAddonSetting('timemax', sType=t.NUM)) ).isoformat() + 'Z' events = googlecal.get_events( TEMP_STORAGE_NOTIFICATIONS,
def __init__(self): self.addtimestamps = t.getAddonSetting('additional_timestamps', sType=t.BOOL)
def get_events(self, storage, timeMin, timeMax, maxResult=30, calendars='primary', evtype='default'): if not os.path.exists(storage) or not t.lastmodified(storage, 60): t.writeLog('establish online connection for getting events') self.establish() events = [] for cal in calendars: cal_items = self.service.events().list( calendarId=cal, timeMin=timeMin, timeMax=timeMax, maxResults=maxResult, singleEvents=True, orderBy='startTime').execute() cal_set = cal_items.get('items', []) # set additional attributes icon = self.get_calendarBGcolorImage(cal) for _record in cal_set: _item = {} _ts = parser.parse(_record['start'].get( 'dateTime', _record['start'].get('date', ''))) _end = parser.parse(_record['end'].get( 'dateTime', _record['end'].get('date', ''))) _tdelta = relativedelta.relativedelta( _end.date(), _ts.date()) _item.update({ 'date': datetime.isoformat(_ts), 'shortdate': _ts.strftime('%d.%m'), 'allday': 0 if _record['start'].get('dateTime') else _tdelta.days, 'timestamp': int(time.mktime(_ts.timetuple())), 'icon': icon, 'id': _record.get('id', ''), 'summary': _record.get('summary', ''), 'description': _record.get('description', None), 'location': _record.get('location', None) }) if _record['start'].get('dateTime', False): _item.update( {'start': { 'dateTime': datetime.isoformat(_ts) }}) else: _item.update( {'start': { 'date': datetime.isoformat(_ts) }}) if _record['end'].get('dateTime', False): _item.update( {'end': { 'dateTime': datetime.isoformat(_end) }}) else: _item.update( {'end': { 'date': datetime.isoformat(_end) }}) gadget = _record.get('gadget', None) if gadget: if gadget.get('preferences').get( 'goo.contactsEventType') == 'BIRTHDAY': _item.update({'specialicon': __cake__}) events.append(_item) # get additional calendars, glotz.info if t.getAddonSetting( 'glotz_enabled', sType=t.BOOL) and t.getAddonSetting('glotz_apikey') != '': if evtype == 'default' or (evtype == 'notification' and t.getAddonSetting( 'glotz_notify', sType=t.BOOL)): t.writeLog('getting events from glotz.info') try: cal_set = json.loads( urllib.urlopen(self.GLOTZ_URL).read()) icon = self.get_calendarBGcolorImage('glotz_color') for _record in cal_set: _item = {} _show = _record.get('show') _time_fmt = 'dateTime' if len(_show.get('airs_time', '')) == 5: _hour = int(_show.get('airs_time')[0:2]) _minute = int(_show.get('airs_time')[3:5]) else: _hour = 0 _minute = 0 _time_fmt = 'date' _ts = datetime.fromtimestamp( int(_record.get('first_aired', '0'))).replace(hour=_hour, minute=_minute) _end = _ts + timedelta( minutes=int(_show.get('runtime', '0')) ) if _time_fmt == 'dateTime' else _ts _item.update({ 'timestamp': int(time.mktime(_ts.timetuple())), 'date': datetime.isoformat(_ts), 'shortdate': _ts.strftime('%d.%m'), 'start': { _time_fmt: datetime.isoformat(_ts) }, 'end': { _time_fmt: datetime.isoformat(_end) }, 'id': '%s-%s-%s' % (_record.get('first_aired', ''), _record.get('season', '0'), _record.get('number', '0')), 'summary': _show.get('network', ''), 'description': '%s - S%02iE%02i: %s' % (_show.get('title', ''), int(_record.get('season', '0')), int(_record.get('number', '0')), _record.get('title', '')), 'icon': icon, 'banner': _show['images'].get('banner', ''), 'allday': 1 if _time_fmt == 'date' else 0 }) events.append(_item) except Exception as e: t.writeLog('Error on line {}'.format( sys.exc_info()[-1].tb_lineno), level=xbmc.LOGERROR) t.writeLog(type(e).__name__, level=xbmc.LOGERROR) t.writeLog(e.message, level=xbmc.LOGERROR) events.sort(key=operator.itemgetter('timestamp')) with open(storage, 'w') as filehandle: json.dump(events, filehandle) else: t.writeLog('getting events from local storage') with open(storage, 'r') as filehandle: events = json.load(filehandle) return events
class Calendar(object): class oAuthMissingSecretFile(Exception): pass class oAuthMissingCredentialsFile(Exception): pass class oAuthIncomplete(Exception): pass class oAuthFlowExchangeError(Exception): pass # If modifying these scopes, delete your previously saved credentials # at ~/.credentials/service.calendar.json CLIENTS_PATH = os.path.join(xbmc.translatePath(__profiles__), '_credentials') if not os.path.exists(CLIENTS_PATH): os.makedirs(CLIENTS_PATH) COLOR_PATH = os.path.join(xbmc.translatePath(__profiles__), '_colors') if not os.path.exists(COLOR_PATH): os.makedirs(COLOR_PATH) SCOPES = 'https://www.googleapis.com/auth/calendar.readonly' CLIENT_SECRET_FILE = os.path.join(xbmc.translatePath(__addonpath__), '_credentials', 'service.calendar.oauth.json') CLIENT_CREDENTIALS = os.path.join(CLIENTS_PATH, 'service.calendar.credits.json') APPLICATION_NAME = 'service.calendar' SHEET_ID = 30008 TEMP_STORAGE_CALENDARS = os.path.join(xbmc.translatePath(__profiles__), 'calendars.json') GLOTZ_URL = 'https://www.glotz.info/v2/user/calendar/%s' % ( t.getAddonSetting('glotz_apikey')) def __init__(self): self.addtimestamps = t.getAddonSetting('additional_timestamps', sType=t.BOOL) def establish(self): credentials = self.get_credentials() http = credentials.authorize(httplib2.Http()) self.service = discovery.build('calendar', 'v3', http=http) def get_credentials(self): if not os.path.isfile(self.CLIENT_SECRET_FILE): raise self.oAuthMissingSecretFile('missing %s' % (self.CLIENT_SECRET_FILE)) storage = Storage(self.CLIENT_CREDENTIALS) credentials = storage.get() if not credentials or credentials.invalid: credentials = self.require_credentials(self.CLIENT_CREDENTIALS) return credentials def require_credentials(self, storage_path, require_from_setup=False, reenter=None): storage = Storage(storage_path) try: flow = client.flow_from_clientsecrets( self.CLIENT_SECRET_FILE, self.SCOPES, redirect_uri='urn:ietf:wg:oauth:2.0:oob') flow.user_agent = self.APPLICATION_NAME auth_code = '' if reenter is None: auth_uri = tinyurl.create_one(flow.step1_get_authorize_url()) if require_from_setup: _dialog = __LS__(30082) else: _dialog = '%s %s' % (__LS__(30081), __LS__(30082)) if not t.dialogYesNo(__LS__(30080), _dialog): raise self.oAuthIncomplete('oAuth2 flow aborted by user') t.dialogOK(__LS__(30080), __LS__(30083)) mail.checkproperties() mail.sendmail( __LS__(30100) % (__addonname__), __LS__(30101) % (auth_uri)) if not t.dialogYesNo(__LS__(30080), __LS__(30087)): raise self.oAuthIncomplete('oAuth2 flow aborted by user') reenter = 'kb' if reenter == 'kb': auth_code = t.dialogKeyboard(__LS__(30084)) elif reenter == 'file': auth_code = t.dialogFile(__LS__(30086)) if auth_code == '': raise self.oAuthIncomplete('no key provided') credentials = flow.step2_exchange(auth_code) storage.put(credentials) except client.FlowExchangeError, e: raise self.oAuthFlowExchangeError(e.message) return credentials
def controller(mode=None, handle=None, content=None, eventId=None): now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0).isoformat() + 'Z' timemax = ( datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) + relativedelta.relativedelta(months=tools.getAddonSetting( 'timemax', sType=tools.NUM))).isoformat() + 'Z' if mode == 'require_oauth_key': Calendar().require_credentials(Calendar().CLIENT_CREDENTIALS, require_from_setup=True) tools.writeLog('new credentials successfull received and stored', xbmc.LOGDEBUG) tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'reenter_oauth_key': Calendar().require_credentials(Calendar().CLIENT_CREDENTIALS, require_from_setup=True, reenter='kb') tools.writeLog('new credentials successfull received and stored', xbmc.LOGDEBUG) tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'load_oauth_key': Calendar().require_credentials(Calendar().CLIENT_CREDENTIALS, require_from_setup=True, reenter='file') tools.writeLog('new credentials successfull received and stored', xbmc.LOGDEBUG) tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'load_glotz_key': glotz_apikey = tools.dialogFile(__LS__(30089)) if glotz_apikey != '': tools.setAddonSetting('glotz_apikey', glotz_apikey) tools.writeLog('API key for glotz.info successfull stored') tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'check_mailsettings': mail = SMTPMail() mail.checkproperties() mail.sendmail( __LS__(30074) % (__LS__(30010), tools.release().hostname), __LS__(30075)) tools.writeLog('mail delivered', xbmc.LOGNOTICE) tools.dialogOK(__LS__(30010), __LS__(30076) % (mail.smtp_client['recipient'])) elif mode == 'abort_reminders': tools.writeLog('abort notification service by setup', xbmc.LOGNOTICE) xbmcgui.Window(10000).setProperty('reminders', '0') elif mode == 'set_calendars': set_localsetting('calendars') googlecal = Calendar() googlecal.get_events( TEMP_STORAGE_EVENTS, now, timemax, maxResult=30, calendars=googlecal.get_calendarIdFromSetup('calendars')) elif mode == 'set_notifications': set_localsetting('notifications') googlecal = Calendar() googlecal.get_events( TEMP_STORAGE_NOTIFICATIONS, now, timemax, maxResult=30, calendars=googlecal.get_calendarIdFromSetup('notifications')) elif mode == 'getcontent': googlecal = Calendar() googlecal.build_sheet( handle, TEMP_STORAGE_EVENTS, content, now, timemax, maxResult=30, calendars=googlecal.get_calendarIdFromSetup('calendars')) elif mode == 'getinfo' and eventId != '': googlecal = Calendar() events = eventId.strip(' ').split(' ') _msg = '' for event in events: _ev = googlecal.get_event(event, TEMP_STORAGE_EVENTS) _mev = googlecal.prepareForAddon(_ev, optTimeStamps=True) _time = '' if _mev.get( 'range', '') == '' else '[B]%s[/B]: ' % (_mev.get('range')) _msg += '%s%s[CR]%s[CR][CR]' % (_time, _mev.get( 'summary', ''), _mev.get('description', False) or _mev.get( 'location', False) or __LS__(30093)) tools.dialogOK( '%s %s %s' % (__LS__(30109), __LS__(30145), _mev.get('shortdate', '')), _msg) elif mode == 'prev': calc_boundaries(-1) elif mode == 'next': calc_boundaries(1) # this is the real controller bootstrap elif mode == 'gui': try: Popup = xbmcgui.WindowXMLDialog(__xml__, __path__) Popup.doModal() del Popup except RuntimeError, e: raise FileNotFoundException('%s: %s' % (e.message, __xml__))
def __init__(self): self.__xml = None self.__recTitles = [] self.__wakeUp = None self.__wakeUpUT = None self.__monitored_ports = '' self.rndProcNum = random.randint(1, 1024) self.hasPVR = None ### read addon settings self.__prerun = tools.getAddonSetting('margin_start', sType=tools.NUM) self.__postrun = tools.getAddonSetting('margin_stop', sType=tools.NUM) self.__shutdown = tools.getAddonSetting('shutdown_method', sType=tools.NUM) self.__sudo = 'sudo ' if tools.getAddonSetting( 'sudo', sType=tools.BOOL) else '' self.__counter = tools.getAddonSetting('notification_counter', sType=tools.NUM) self.__nextsched = tools.getAddonSetting('next_schedule', sType=tools.BOOL) # TVHeadend server self.__maxattempts = tools.getAddonSetting('conn_attempts', sType=tools.NUM) self.hasPVR = True try: __addonTVH__ = xbmcaddon.Addon('pvr.hts') self.__server = 'http://' + __addonTVH__.getSetting('host') self.__port = __addonTVH__.getSetting('http_port') self.__user = __addonTVH__.getSetting('user') self.__pass = __addonTVH__.getSetting('pass') except RuntimeError: tools.writeLog('Addon \'pvr.hts\' not installed or inactive', level=xbmc.LOGERROR) self.hasPVR = False # check if network activity has to observed self.__network = tools.getAddonSetting('network', sType=tools.BOOL) self.__monitored_ports = self.createwellformedlist('monitored_ports') # check if processes has to observed self.__pp_enabled = tools.getAddonSetting('postprocessor_enable', sType=tools.BOOL) self.__pp_list = self.createwellformedlist('processor_list') # mail settings self.__notification = tools.getAddonSetting('smtp_sendmail', sType=tools.BOOL) self.__smtpserver = tools.getAddonSetting('smtp_server') self.__smtpuser = tools.getAddonSetting('smtp_user') self.__smtppass = self.crypt('smtp_passwd', 'smtp_key', 'smtp_token') self.__smtpenc = tools.getAddonSetting('smtp_encryption') self.__smtpfrom = tools.getAddonSetting('smtp_from') self.__smtpto = tools.getAddonSetting('smtp_to') self.__charset = tools.getAddonSetting('charset') # EPG-Wakeup settings self.__epg_interval = tools.getAddonSetting('epgtimer_interval', sType=tools.NUM) self.__epg_time = tools.getAddonSetting('epgtimer_time', sType=tools.NUM) self.__epg_duration = tools.getAddonSetting('epgtimer_duration', sType=tools.NUM) self.__epg_grab_ext = tools.getAddonSetting('epg_grab_ext', sType=tools.BOOL) self.__epg_socket = xbmc.translatePath( tools.getAddonSetting('epg_socket_path')) self.__epg_store = tools.getAddonSetting('store_epg', sType=tools.BOOL) self.__epg_path = xbmc.translatePath( os.path.join(tools.getAddonSetting('epg_path'), 'epg.xml')) tools.writeLog('Settings loaded')
def createwellformedlist(cls, setting): ''' transform possible ugly userinput (e.g. 'p1, p2,, p3 p4 ') to a shapely list ''' return ' '.join( tools.getAddonSetting(setting).replace(',', ' ').split()).split()
os.path.join(__path__, 'resources', 'lib', 'epggrab_ext.sh')) # set permissions for these files, this is required after installation or update _sts = os.stat(SHUTDOWN_CMD) _stg = os.stat(EXTGRABBER) if not (_sts.st_mode & stat.S_IEXEC): os.chmod(SHUTDOWN_CMD, _sts.st_mode | stat.S_IEXEC) if not (_stg.st_mode & stat.S_IEXEC): os.chmod(EXTGRABBER, _stg.st_mode | stat.S_IEXEC) CYCLE = 15 # polling cycle tools.writeLog('OS ID is %s' % (release.osid)) if ('libreelec' or 'openelec') in release.osid and tools.getAddonSetting( 'sudo', sType=tools.BOOL): __addon__.setSetting('sudo', 'false') tools.writeLog( 'OS is LibreELEC or OpenELEC, reset wrong setting \'sudo\' in options') # binary Flags isRES = 0b10000 # TVH PM has started by Resume on record/EPG isNET = 0b01000 # Network is active isPRG = 0b00100 # Programs/Processes are active isREC = 0b00010 # Recording is or becomes active isEPG = 0b00001 # EPG grabbing is active isUSR = 0b00000 # User is active class Manager(object):
def main(mode=None, handle=None, content=None): now = datetime.utcnow().isoformat() + 'Z' timemax = (datetime.utcnow() + relativedelta.relativedelta( months=tools.getAddonSetting('timemax', sType=tools.NUM)) ).isoformat() + 'Z' if mode == 'require_oauth_key': Calendar().require_credentials(Calendar().CLIENT_CREDENTIALS, require_from_setup=True) tools.writeLog('new credentials successfull received and stored', xbmc.LOGDEBUG) tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'reenter_oauth_key': Calendar().require_credentials(Calendar().CLIENT_CREDENTIALS, require_from_setup=True, reenter='kb') tools.writeLog('new credentials successfull received and stored', xbmc.LOGDEBUG) tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'load_oauth_key': Calendar().require_credentials(Calendar().CLIENT_CREDENTIALS, require_from_setup=True, reenter='file') tools.writeLog('new credentials successfull received and stored', xbmc.LOGDEBUG) tools.Notify().notify(__LS__(30010), __LS__(30073)) elif mode == 'check_mailsettings': mail = SMTPMail() mail.checkproperties() mail.sendmail( __LS__(30074) % (__LS__(30010), tools.release().hostname), __LS__(30075)) tools.writeLog('mail delivered', xbmc.LOGNOTICE) tools.dialogOK(__LS__(30010), __LS__(30076) % (mail.smtp_client['recipient'])) elif mode == 'abort_reminders': tools.writeLog('abort notification service by setup', xbmc.LOGNOTICE) xbmcgui.Window(10000).setProperty('reminders', '0') elif mode == 'set_calendars': set_localsetting('calendars') googlecal = Calendar() googlecal.get_events( TEMP_STORAGE_EVENTS, now, timemax, maxResult=30, calendars=googlecal.get_calendarIdFromSetup('calendars')) elif mode == 'set_notifications': set_localsetting('notifications') googlecal = Calendar() googlecal.get_events( TEMP_STORAGE_NOTIFICATIONS, now, timemax, maxResult=30, calendars=googlecal.get_calendarIdFromSetup('notifications')) elif mode == 'getcontent': googlecal = Calendar() googlecal.build_sheet( handle, TEMP_STORAGE_EVENTS, content, now, timemax, maxResult=30, calendars=googlecal.get_calendarIdFromSetup('calendars')) elif mode == 'prev': calc_boundaries(-1) elif mode == 'next': calc_boundaries(1) # this is the real controller bootstrap elif mode == 'gui': try: Popup = xbmcgui.WindowXMLDialog(__xml__, __path__) Popup.doModal() del Popup except RuntimeError, e: raise FileNotFoundException('%s: %s' % (e.message, __xml__))