def select_date(self): # すべての日付 name = '[COLOR lightgreen]%s[/COLOR]' % Common.STR(30912) if self.args.get('ch') is None: mode = 'selectChannel' elif self.args.get('g0') is None: mode = 'selectGenre' else: mode = 'search' self.add_directory_item(name, '%s&sdate=&edate=' % self.query, mode, iconimage=Common.CALENDAR) # 月,火,水,木,金,土,日 w = Common.STR(30920).split(',') for i in range(120): d = datetime.date.today() - datetime.timedelta(i) wd = d.weekday() # 月日 # date1 = '%s(%s)' % (d.strftime(Common.STR(30919)), w[wd]) date1 = '%s(%s)' % (Common.strftime(d, Common.STR(30919)), w[wd]) date2 = d.strftime('%Y-%m-%d') if Common.isholiday(date2) or wd == 6: name = '[COLOR red]%s[/COLOR]' % date1 elif wd == 5: name = '[COLOR blue]%s[/COLOR]' % date1 else: name = date1 query = '%s&sdate=%s 00:00:00&edate=%s 23:59:59' % (self.query, date2, date2) if self.args.get('ch') is None: mode = 'selectChannel' elif self.args.get('g0') is None: mode = 'selectGenre' else: mode = 'search' self.add_directory_item(name, query, mode, iconimage=Common.CALENDAR) # end of directory xbmcplugin.endOfDirectory(int(sys.argv[1]))
def add_directory_item(self, name, url, mode, context='', iconimage=''): # listitem listitem = xbmcgui.ListItem(name) listitem.setArt({'icon': iconimage}) # context menu contextMenu = [] if context == 'smartlist': # スマートリストを編集 contextMenu.append(( Common.STR(30904), 'RunPlugin(%s?%s)' % (sys.argv[0], urlencode({'mode': 'beginEditSmartList', 'name': name})))) # スマートリストを削除 contextMenu.append(( Common.STR(30905), 'RunPlugin(%s?%s)' % (sys.argv[0], urlencode({'mode': 'deleteSmartList', 'name': name})))) elif context != 'top': # トップに戻る contextMenu.append(( Common.STR(30936), 'Container.Update(%s,replace)' % (sys.argv[0]))) # アドオン設定 contextMenu.append((Common.STR(30937), 'RunPlugin(%s?mode=openSettings)' % sys.argv[0])) listitem.addContextMenuItems(contextMenu, replaceItems=True) # add directory item url = '%s?%s' % (sys.argv[0], urlencode({'mode': mode, 'url': url})) xbmcplugin.addDirectoryItem(int(sys.argv[1]), url, listitem, True)
def get_contextmenu(self): gtvid = self.item['gtvid'] title = self.item['title'] menu = [] # 詳細情報 menu.append((Common.STR(30906), 'Action(Info)')) # スマートリストに追加 try: if self.item['genre'][0]: genre = self.item['genre'][0].split('/') else: genre = ['', ''] except Exception: genre = ['', ''] args = { 'mode': 'beginEditSmartList', 'name': title, 'ch': self.item['ch'], 'g0': genre[0], 'g1': genre[1] } menu.append((Common.STR(30903), 'RunPlugin(%s?%s)' % (sys.argv[0], urlencode(args)))) # お気に入りに追加 if self.item['favorite'] == '0': # add args = { 'mode': 'switchFavorites', 'name': title, 'url': urlencode({ 'gtvid': gtvid, 'rank': 1 }) } menu.append((Common.STR(30925), 'RunPlugin(%s?%s)' % (sys.argv[0], urlencode(args)))) else: # delete args = { 'mode': 'switchFavorites', 'name': title, 'url': urlencode({ 'gtvid': gtvid, 'rank': 0 }) } menu.append((Common.STR(30926), 'RunPlugin(%s?%s)' % (sys.argv[0], urlencode(args)))) # サウンロードに追加 menu += Downloader().contextmenu(self.item, Request().content_url(gtvid)) # トップに戻る menu.append((Common.STR(30936), 'Container.Update(%s,replace)' % (sys.argv[0]))) return menu
def show_history(self, name): # ディレクトリ cache_dir = os.path.join(Common.CACHE_PATH, name) if not os.path.isdir(cache_dir): os.makedirs(cache_dir) # ファイルリスト count = 0 files = sorted(os.listdir(cache_dir), key=lambda message: os.stat( os.path.join(cache_dir, message)).st_mtime, reverse=True) for filename in files: path = os.path.join(cache_dir, filename) if os.path.isfile(path) and not filename.startswith('.'): if self.listsize == 0 or count < self.listsize: content = Common.read_file(path) # 日付文字列 d = datetime.datetime.fromtimestamp(os.stat(path).st_mtime) weekday = d.weekday() date1 = Common.strftime( d, Common.STR(32901) ) + '(%s)' % Common.STR(32902).split(',')[weekday] time1 = d.strftime('%H:%M:%S') if weekday == 6 or Common.isholiday( d.strftime('%Y-%m-%d')): template = '[COLOR red]%s %s[/COLOR]' elif weekday == 5: template = '[COLOR blue]%s %s[/COLOR]' else: template = '%s %s' fd = template % (date1, time1) # リストアイテム label = '%s %s' % (fd, content) listitem = xbmcgui.ListItem(label) listitem.setArt({ 'iconImage': 'DefaultFile.png', 'thumb': 'DefaultFile.png' }) values = {'action': 'message', 'name': name, 'path': path} query = '%s?%s' % (sys.argv[0], urlencode(values)) # コンテクストメニュー menu = [] # アドオン設定 menu.append((Common.STR(32900), 'Addon.OpenSettings(%s)' % Common.ADDON_ID)) # 追加 listitem.addContextMenuItems(menu, replaceItems=True) xbmcplugin.addDirectoryItem(int(sys.argv[1]), query, listitem, False) # カウントアップ count += 1 else: os.remove(path) # end of directory xbmcplugin.endOfDirectory(int(sys.argv[1]))
class Channel(): DEFAULT_NAME = '[COLOR lightgreen]%s[/COLOR]' % Common.STR(30913) # すべてのチャンネル def __init__(self): self.data = Common.read_json(Common.CHANNEL_FILE) def search(self, key): result = {'id': '', 'name': '', 'hash': ''} for key, val in filter(lambda x: key in {x[0], x[1]['ch_name'], x[1]['hash_tag']}, self.data['ch_list'].items()): result['id'] = key result['name'] = val['ch_name'] result['hash'] = val['hash_tag'] return result def getList(self): result = [{'id': '', 'name': self.DEFAULT_NAME}] for key, value in self.data['ch_list'].items(): result.append({'id': key, 'name': value['ch_name']}) return sorted(result, key=lambda item: item['id']) def getLabel(self): return '|'.join(map(lambda x: x['name'], self.getList())) def getDefault(self): return self.DEFAULT_NAME
def open(self, filename): # ファイル読み込み filepath = os.path.join(self.cache_path, filename) f = open(filepath, 'r') lines = f.readlines() f.close() # パース header = [] body = [] params = {'Subject': Common.STR(30901), 'body': False} for line in lines: line = line.rstrip() if params['body'] is True: body.append(line) elif line == '': params['body'] = True else: pair = line.split(': ', 1) if len(pair) == 2: params[pair[0]] = pair[1] if pair[0] != 'Subject' and pair[0] != 'Message-Id': header.append('[COLOR green]%s:[/COLOR] %s' % (pair[0], pair[1])) # テキストビューア viewer_id = 10147 # ウィンドウを開く xbmc.executebuiltin('ActivateWindow(%s)' % viewer_id) # ウィンドウの用意ができるまで1秒待つ xbmc.sleep(1000) # ウィンドウへ書き込む viewer = xbmcgui.Window(viewer_id) viewer.getControl(1).setLabel('[COLOR orange]%s[/COLOR]' % params['Subject']) viewer.getControl(5).setText('%s\n\n%s' % ('\n'.join(header), '\n'.join(body)))
def top(self): # 放送中の番組 self.add_directory_item(Common.STR(30916), self.query, 16, context='top', iconimage=Common.RETRO_TV) # 検索:日付 self.add_directory_item(Common.STR(30933), '', 'selectDate', context='top', iconimage=Common.CALENDAR) # 検索:チャンネル self.add_directory_item(Common.STR(30934), '', 'selectChannel', context='top', iconimage=Common.RADIO_TOWER) # 検索:ジャンル self.add_directory_item(Common.STR(30935), '', 'selectGenre', context='top', iconimage=Common.CATEGORIZE) # お気に入り self.add_directory_item(Common.STR(30923), '%s&rank=all' % self.query, 'search', context='top', iconimage=Common.FAVORITE_FOLDER) # ダウンロード Downloader().top(Common.DOWNLOADS_FOLDER) # スマートリスト for i in SmartList().getList(): title = i['title'] query = i['query'] self.add_directory_item(title, query, 'search', context='smartlist', iconimage=Common.BROWSE_FOLDER) # end of directory xbmcplugin.endOfDirectory(int(sys.argv[1]))
def lookup(uri): name = None key = parse(uri) # 0で始まって9桁以上ある場合は電話番号として先ず電話帳、次にキャッシュ、最後にウェブを検索 if re.compile('^0[0-9]{8,}').search(key): # 電話帳を検索 name = PhoneBook().lookup(key) if name is None: # キャッシュを検索 cache = PhoneBook(Common.CACHE_FILE) name = cache.lookup(key) if name is None: # ウェブを検索 name = search(key) if name: # キャッシュに追加 cache.update(key, name or 'n/a') elif name == 'n/a': name = None # 以下は # http://www.ttc.or.jp/jp/document_list/pdf/j/STD/JJ-90.22v1.1.pdf # による elif key == 'Anonymous': # ユーザ拒否のため通知不可 name = Common.STR(32908) elif key == 'Coin line/payphone': # 公衆電話発信のため通知不可 name = Common.STR(32909) elif key == 'Unavailable': # 通知可能な情報が存在しない name = Common.STR(32910) elif key == 'Interaction with other service': # サービス競合のため通知不可 name = Common.STR(32910) # 検索結果 name = name or key or uri # 履歴に追加 History().append(uri, key or 'n/a', name or 'n/a') return name, key
def show(self): for key, name in sorted(self.data.items()): # 電話帳エントリ - リストアイテム title = '%s [COLOR lightgreen]%s[/COLOR]' % (key, name) li = xbmcgui.ListItem(title) li.setArt({'icon': Common.CONTACTS, 'thumb': Common.CONTACTS}) # 履歴 - コンテクストメニュー menu = [] action = 'RunPlugin(%s?action=beginEditPhoneBookItem&key=%s&name=%s)' % ( sys.argv[0], quote_plus(key), quote_plus(name)) menu.append((Common.STR(32905), action)) action = 'RunPlugin(%s?action=removePhoneBookItem&key=%s&name=%s)' % ( sys.argv[0], quote_plus(key), quote_plus(name)) menu.append((Common.STR(32906), action)) action = 'RunPlugin(%s?action=settings)' % (sys.argv[0]) menu.append((Common.STR(32902), action)) li.addContextMenuItems(menu, replaceItems=True) # リストアイテムを追加 url = '' xbmcplugin.addDirectoryItem(int(sys.argv[1]), url, listitem=li) # リストアイテム追加完了 xbmcplugin.endOfDirectory(int(sys.argv[1]))
def show_tokens(self): for name in self.data.keys(): listitem = xbmcgui.ListItem(name) listitem.setArt({ 'iconImage': 'DefaultFolder.png', 'thumb': 'DefaultFolder.png' }) query = '%s?action=history&name=%s' % (sys.argv[0], quote(name)) # コンテクストメニュー menu = [] # トークン削除 menu.append((Common.STR(32905), 'RunPlugin(%s?action=deletetoken&name=%s)' % (sys.argv[0], quote(name)))) # アドオン設定 menu.append((Common.STR(32900), 'Addon.OpenSettings(%s)' % Common.ADDON_ID)) # 追加 listitem.addContextMenuItems(menu, replaceItems=True) xbmcplugin.addDirectoryItem(int(sys.argv[1]), query, listitem, True) # end of directory xbmcplugin.endOfDirectory(int(sys.argv[1]))
def search(self, onair=False, retry=True): # 検索 response_body = Request().search(self.query) if response_body: response_data = json.loads(response_body) if response_data['status'] == 1: # 検索結果の番組 programs = response_data['program'] if onair: # 放送中の番組はチャンネル順 for item in sorted(programs, key=lambda item: item['ch']): if item.get('ts') == 1: self.add_item(item, onair) # 放送中の番組の更新を設定 UpdateOnAir(programs).set_timer() else: # 放送済みの番組は時間降順 for item in sorted(programs, key=lambda item: item['startdate'], reverse=True): if item.get('ts') == 1: self.add_item(item, onair) # 検索結果の続きがある場合は次のページへのリンクを表示 hit = int(response_data['hit']) page = int(self.args.get('p')) if hit > page * Common.ITEMS: self.args['p'] = page + 1 query = urlencode(self.args) # 次のページへ self.add_directory_item('[COLOR lightgreen]%s[/COLOR]' % (Common.STR(30922)), query, 'search', iconimage=Common.RIGHT) # end of directory xbmcplugin.endOfDirectory(int(sys.argv[1])) elif retry is True: # セッションを初期化してリトライする if initializeSession(): if checkSettings(): self.search(onair, retry=False) else: Common.log('invalid settings', error=True) Common.notify('Search failed') else: Common.log('session initialization failed', error=True) Common.notify('Search failed') else: # リトライも失敗 Common.log('retry failed', error=True) Common.notify('Search failed') else: Common.log('empty response', error=True) Common.notify('Search failed')
def convert(self, item): # extract filename & timestamp filename = re.match('^<?(.*?)>?$', item['Message-Id']).group(1) timestamp = email.utils.mktime_tz( email.utils.parsedate_tz(item['Date'])) # date - self.convert by strftime accrding to format string defined as 30902 parsed = email.utils.parsedate_tz(item['Date']) t = email.utils.mktime_tz(parsed) item['Date'] = time.strftime(Common.STR(30902), time.localtime(t)) # body - extract plain text from html using beautifulsoup decoded_body = item['body'] if re.compile(r'<html|<!doctype', re.IGNORECASE).match(decoded_body): decoded_body = re.compile(r'<style.*?</style>', re.DOTALL | re.MULTILINE | re.IGNORECASE).sub('', decoded_body) decoded_body = re.compile(r'<script.*?</script>', re.DOTALL | re.MULTILINE | re.IGNORECASE).sub('', decoded_body) soup = BeautifulSoup(decoded_body, 'html.parser') buf = [] for text in soup.stripped_strings: buf.append(text) item['body'] = ' '.join(buf) return filename, timestamp
def show(self): # 曜日表記 w = Common.STR(32900).split(',') # 履歴表示 for h in reversed(self.data): # 履歴 date = h['date'] time = h['time'] wday = h['weekday'] uri = h['uri'] key = h['key'] name = h['name'] datetime = '%s(%s) %s' % (date, w[wday], time) # コンテクストメニュー menu = [] if re.compile('^0[0-9]{8,}').search(key): if PhoneBook().lookup(key): template2 = '[COLOR lightgreen]%s[/COLOR]' action = 'RunPlugin({url}?action=beginEditPhoneBookItem&{query})'.format( url=sys.argv[0], query=urlencode({ 'key': key, 'name': name })) menu.append((Common.STR(32904), action)) else: template2 = '[COLOR khaki]%s[/COLOR]' action = 'RunPlugin({url}?action=addPhoneBookItem&{query})'.format( url=sys.argv[0], query=urlencode({ 'key': key, 'name': name })) menu.append((Common.STR(32903), action)) else: key = '' template2 = '[COLOR orange]%s[/COLOR]' action = 'Container.Update(%s?action=showPhoneBook)' % ( sys.argv[0]) menu.append((Common.STR(32907), action)) action = 'RunPlugin(%s?action=settings)' % (sys.argv[0]) menu.append((Common.STR(32902), action)) # 書式 if Common.isholiday(date) or wday == 6: template1 = '[COLOR red]%s[/COLOR]' elif wday == 5: template1 = '[COLOR blue]%s[/COLOR]' else: template1 = '%s' template3 = '%s' template = '%s %s %s' % (template1, template3, template2) title = template % (datetime, key, name) li = xbmcgui.ListItem(title) li.setArt({ 'icon': Common.RINGER_VOLUME, 'thumb': Common.RINGER_VOLUME }) li.addContextMenuItems(menu, replaceItems=True) # 履歴 - 追加 url = '' xbmcplugin.addDirectoryItem(int(sys.argv[1]), url, listitem=li) # リストアイテム追加完了 xbmcplugin.endOfDirectory(int(sys.argv[1]))
def onIncomingCall(self, param): # ログ Common.log('\n'.join([ # https://www.pjsip.org/pjsip/docs/html/structpj_1_1OnIncomingCallParam.htm 'callId: %s' % param.callId, # 'rdata: %s' % param.rdata, 'rdata.info: %s' % param.rdata.info, 'rdata.wholeMsg: \n-----\n%s\n-----' % '\n'.join(param.rdata.wholeMsg.strip().split('\r\n')), 'rdata.srcAddress: %s' % param.rdata.srcAddress, 'rdata.pjRxData: %s' % param.rdata.pjRxData, ])) call = pj.Call(self, param.callId) info = call.getInfo() Common.log('\n'.join([ # https://www.pjsip.org/pjsip/docs/html/structpj_1_1CallInfo.htm 'id: %s' % info.id, 'role: %s' % info.role, 'accId: %s' % info.accId, 'localUri: %s' % info.localUri, 'localContact: %s' % info.localContact, 'remoteUri: %s' % info.remoteUri, 'remoteContact: %s' % info.remoteContact, 'callIdString: %s' % info.callIdString, # 'setting: %s' % info.setting, 'setting.flag: %s' % info.setting.flag, 'setting.reqKeyframeMethod: %s' % info.setting.reqKeyframeMethod, 'setting.audioCount: %s' % info.setting.audioCount, 'setting.videoCount: %s' % info.setting.videoCount, 'state: %s' % info.state, 'stateText: %s' % info.stateText, 'lastStatusCode: %s' % info.lastStatusCode, 'media: %s' % info.media, 'provMedia: %s' % info.provMedia, 'connectDuration: %d.%03d' % (info.connectDuration.sec, info.connectDuration.msec), 'totalDuration: %d.%03d' % (info.totalDuration.sec, info.totalDuration.msec), 'remOfferer: %s' % info.remOfferer, 'remAudioCount: %s' % info.remAudioCount, 'remVideoCount: %s' % info.remVideoCount, ])) # Kodiをアクティベート if Common.GET('cec') == 'true': xbmc.executebuiltin('CECActivateSource') # 発信者番号から番号検索 name, key = lookup(info.remoteUri) local = parse(info.localUri) # 通知 duration = Common.GET('duration') Common.notify(name, time=int(duration) * 1000) # メールによる通知 if Common.GET('mailaddon') and Common.GET('mailnotify') == 'true': template = Common.GET('mailtemplate') or Common.STR(32913) address = Common.GET('mailaddress') message = template.format(name=name, key=key, local=local) xbmc.executebuiltin('RunPlugin("plugin://%s?%s")' % (Common.GET('mailaddon'), urlencode({ 'action': 'send', 'subject': message, 'message': message, 'to': address }))) # LINE notifyによる通知 if Common.GET('lineaddon') and Common.GET('linenotify') == 'true': template = Common.GET('linetemplate') or Common.STR(32913) token = Common.GET('linetoken') message = template.format(name=name, key=key, local=local) xbmc.executebuiltin('RunPlugin("plugin://%s?%s")' % (Common.GET('lineaddon'), urlencode({ 'action': 'send', 'name': token, 'message': message })))
def list(self, newmails): # ファイルリスト files = sorted(os.listdir(self.cache_path), key=lambda mail: os.stat( os.path.join(self.cache_path, mail)).st_mtime, reverse=True) # ファイルの情報を表示 count = 0 for filename in files: filepath = os.path.join(self.cache_path, filename) if os.path.isfile(filepath) and not filename.startswith('.'): if self.listsize == 0 or count < self.listsize: # ファイル読み込み f = open(filepath, 'r') lines = f.readlines() f.close() # パース params = { 'Subject': '', 'From': '', 'body': False, 'messages': [] } for line in lines: line = line.rstrip() if line == '': params['body'] = True elif params['body'] is True: if line.startswith('?') or line.startswith('?'): message = line[1:].strip() if message: params['messages'].append(message) elif params['body'] is False: pair = line.split(': ', 1) if len(pair) == 2: params[pair[0]] = pair[1] # GUI設定 if params['Subject']: title = params['Subject'] else: title = Common.STR(30901) if filepath in newmails: title = '[COLOR yellow]%s[/COLOR]' % title # 日付文字列 d = datetime.datetime.fromtimestamp( os.stat(filepath).st_mtime) # リストアイテム label = '%s %s' % (Common.datetime(d), title) listitem = xbmcgui.ListItem(label) listitem.setArt({ 'icon': 'DefaultFile.png', 'thumb': 'DefaultFile.png' }) query = '%s?action=open&filename=%s' % (sys.argv[0], quote(filename)) # コンテクストメニュー menu = [] # 返信 to = params.get('From', '') cc = params.get('CC', '') subject = params.get('Subject', '') values = { 'action': 'prepmessage', 'subject': 'Re: %s' % subject, 'message': '', 'to': to, 'cc': cc } postdata = urlencode(values) menu.append((Common.STR(30800), 'RunPlugin(%s?%s)' % (sys.argv[0], postdata))) # 新着確認 menu.append( (Common.STR(30801), 'Container.Update(%s,replace)' % (sys.argv[0]))) # アドオン設定 menu.append((Common.STR(30802), 'Addon.OpenSettings(%s)' % (Common.ADDON_ID))) # 追加 listitem.addContextMenuItems(menu, replaceItems=True) xbmcplugin.addDirectoryItem(int(sys.argv[1]), query, listitem, False) # カウントアップ count += 1 else: os.remove(filepath) # 表示対象がない場合 if count == 0: title = '[COLOR gray]%s[/COLOR]' % Common.STR(30903) listitem = xbmcgui.ListItem(title) listitem.setArt({ 'icon': 'DefaultFolder.png', 'thumb': 'DefaultFolder.png' }) # コンテクストメニュー menu = [] # 新着確認 menu.append((Common.STR(30801), 'Container.Update(%s,replace)' % (sys.argv[0]))) # アドオン設定 menu.append((Common.STR(30802), 'Addon.OpenSettings(%s)' % (Common.ADDON_ID))) # 追加 listitem.addContextMenuItems(menu, replaceItems=True) xbmcplugin.addDirectoryItem(int(sys.argv[1]), '', listitem, False) xbmcplugin.endOfDirectory(int(sys.argv[1]))