
みなさんこんにちは。 準備されたレポートへのアクセスを提供することは、しばしば別の問題です。 管理のためのデータ処理結果への利便性と運用アクセスの問題が、それらのさらなる使用の運命を大きく左右します。 Tableauシステム(または単にスコアボード)は、このようなタスクではあまり人気がなく、多くのソースからのデータをすばやく分析したり、オンラインレポートをサーバーに公開したり、レポートのPDFバージョンの自動配信を構成したりすることができます。
ただし、すべてがセットアップされ、公開され、配布されたとしても、同僚は問題に直面します。
- 定期的な郵便報告は、仕事の手紙の流れで失われ、すぐに正しいものを見つけることが常に可能とは限りません。
- 原則として、レポートへのオンラインアクセスは企業VPNによって保護されています。 状況によっては、これは問題です。
- 通常、定期的な配布を待たずにレポートを受信する必要があります。 たとえば、現在の月のプロジェクトの計画事実は、いつでも必要になる場合があります。
- サーバー上のアカウントのパスワードが忘れられたり、他の100500フォルダーやレポートの中から目的のレポートを見つけることが困難な場合があります。
このような問題の解決策の1つは、ボタンをクリックするだけでスコアボードサーバーからPDFレポートをエクスポートしてユーザーに送信できるテレグラムボットです。 この記事では、このようなボットの最も単純なバージョンのコードと例を見ていきます。
次の簡略化から進みます。
- ボットのキーボードは、このユーザーに送信するレポートの名前で構成されています。 現在のバージョンのサブメニューの存在は暗示されていません。
- ボットは、すべてのメッセージを互いに独立して処理します。つまり、ユーザーの以前のメッセージを「記憶」しません。
- レポートへのアクセスの有無は、ボットで作業を開始するときに(STARTボタンを押して)各ユーザーに割り当てられたchat_idパラメーターによって決まります。
- ボットには1人の管理者がいて、レポートにアクセスするためのアプリケーションを受け取ります。
この記事では、Amazon Web Services仮想マシンにインストールされているTableau Server 10.1.3のバージョンを使用しました:Windows Server 2016 64ビット、RAM 16GB(はい、ScoreboardサーバーはWindows Serverでのみ動作します)。 エクスポートされたレポートの例は、スコアボードサーバーと共にデフォルトでインストールされるTableauサンプルプロジェクトから取得されました。 たとえば、これ:

Telegramでボットを作成する方法の優れた例はたくさんありますが、 ドキュメントを使用するだけです。 Telegram APIを使用するには、既製のPythonライブラリを使用します 。 Python 2.7 Anacondaを使用します。
B-セキュリティ
Telegramを使用すると、企業サーバーから外部のどこかにレポートを送信できます。 したがって、誰もが自分に割り当てられたレポートのみを受信できるように、アクセスレジストリを維持する必要があります。 また、スクリプトを再起動せずにユーザー/権限を追加する必要があります。 ボットで作業を開始するときにユーザーのchat_idを見つけ、すぐに必要なアクセス権を与えます。
ユーザーがボットの操作を開始したら、chat_idを確認する必要があります。 これを行うには、/ startコマンドハンドラー(コードのstart関数)で、chat_idをボットの管理者に送信します。ボットの管理者は、このユーザーのレポート(つまり、chat_id)でキーボードを作成できます。
STARTボタンが押されると、ユーザーIvan Ivanovは次のメッセージを受け取ります。
こんにちは、現在、レポートにはアクセスできません。 申し込みが承認されました。近い将来アクセスが許可されます。
ボット管理者は次のメッセージを受け取ります:
アクセスの申請iivanov Ivan Ivanov 123456789
このような手順のために、YAMLファイルを作成します。このファイルでは、各ユーザーのユーザーセクションで、必要なレポートを含む「キーボード」を作成します。 この形式は、スクリプトで読み取り、キーボードの形でTelegramに送信するのが非常に簡単です。
ユーザーアクセス構成ファイル
users: 123456789: keyboard: - # , - buttonText: 'Global Temperatures' # , reportName: 'Global Temperatures' # report: '/views/Regional/GlobalTemperatures' # , - buttonText: 'College Admissions' # , reportName: 'College Admissions' # report: '/views/Regional/College' - # , - buttonText: 'Regional FlightDelays' # , reportName: 'Regional FlightDelays' # report: '/views/Regional/FlightDelays'
この実施形態では、キーボードは2つの行を含む:

このようなキーボードエントリをテレグラム形式に変換することは、特別な機能になります。
Telegramのキーボード形成
def makeCustomKeyboard( userKeyboard ): """ . keyboard privacy.yaml. """ custom_keyboard = map( lambda z: [ telegram.KeyboardButton(x['buttonText']) for x in z ], userKeyboard ) return telegram.ReplyKeyboardMarkup(custom_keyboard, resize_keyboard='True')
スクリプトコード内の構成ファイルのアドレスは、変数CONFIG_FILEによって設定されます。 ボットの操作中にこれらのパラメーターを更新するには、updateSettings()関数を使用します。
/ startコマンドとメッセージの処理機能は、毎回アクセスレジストリを更新します。
def updateSettings(): """ """ return load( file( CONFIG_FILE ) )
Scoreboardサーバーを操作するためのアクセスファイルに加えて、次のパラメーターが必要です。
ボットトークンとサーバー設定
config: # botToken: '111222333:AAO4L0Ttt1tt01-1TtT1t_t22tT' # tabcmd.exe tabcmdLocation: 'C:\Program Files\Tableau\Tableau Server\10.1\bin\' # reportsLocation: 'C:\Users\Administrator\Documents\bot\reports\' # logsLocation: 'C:\Users\Administrator\Documents\bot\logs\' admin: # chat id id: 198765432
すべての準備が整ったら、/ startコマンドの処理機能を定義できます。 また、ログ機能は便利です。ボットを使用したアクションのユーザーのchat_idをテキストファイルに書き込むだけです。 エラーが発生した場合のこのような単純なオプションにより、エラーが発生した行がわかります。
コマンド処理/開始
def start(bot, update): """ /start . ( privacy.yaml, users). , . """ # chat_id chat_id = update.message.chat_id # config = updateSettings() # if chat_id in config['users']: logs(update, 'Received /start command from user in privacy.yaml') # reply_markup = makeCustomKeyboard(config['users'][int(chat_id)]['keyboard']) bot.sendMessage(chat_id=chat_id, text=', ', reply_markup=reply_markup) logs(update, 'List of available reports sent') # else: logs(update, 'Received /start command from user NOT IN privacy.yaml') # bot.sendMessage(chat_id=chat_id, text=', . ' + \ ' , ') # u = ast.literal_eval(str(update)) bot.sendMessage(chat_id=config['admin']['id'], text=' ' + str(u['message']['from']['username'].encode('utf-8')) + ' ' + str(u['message']['from']['first_name'].encode('utf-8')) + ' ' + str(u['message']['from']['last_name'].encode('utf-8')) + ' ' + str(chat_id)) logs(update, 'Request for access sent')
わかりました、レポートを利用できるキーボードをユーザーに送信しました。 このバージョンでは、着信メッセージを、このchat_idのprivacy.yamlアクセスファイル内のレポート名と比較する必要があります。 受信したメッセージがレポートの1つと一致する場合、このレポートをエクスポートするコマンドをScoreboardサーバーに送信します。 そして、生成されたレポートをユーザーに送信します。
サーバーからレポートをPDF形式でエクスポートするコマンドは、コマンドラインから「get」または「export」を使用して送信できます(ドキュメントへのリンク )。
これを行うには、最初にスコアボードサーバーとのセッションを開きます(localhost、adminおよびadminPasswordの代わりに、スコアボードサーバードメイン、ユーザー名、およびパスワードを指定します)。
「重い」レポートをエクスポートする前に、ユーザーに警告しておくと便利です。
bot.sendMessage(chat_id=chat_id, text=' , ...', reply_markup=reply_markup) executeFile = os.path.join( tabcmdLocation, 'tabcmd.exe' ) subprocess.call([ executeFile, 'login', '-s', 'localhost', '-u', 'admin', '-p', 'adminPassword '])
レポートをディスク上のフォルダーにエクスポートします
subprocess.call([ executeFile, 'get', reportAddress, '-f', reportsLocation + reportName + '.pdf'])
サーバー上のセッションを閉じます
subprocess.call([ executeFile, 'logout'])
生成されたレポートをユーザーに送信するだけです
bot.send_document(chat_id=chat_id, document=open(reportsLocation + reportName.encode('utf-8') + '.pdf', 'rb'))
仕組みを確認しましょう。

サーバーからエクスポートされたPDFレポート:

それだけです。このアプローチがレポートへのアクセスを簡素化し、作業効率を向上させることを願っています。 コードのフルバージョン:
構成ファイル
users: 123456789: keyboard: - # , - buttonText: 'Global Temperatures' # , reportName: 'Global Temperatures' # report: '/views/Regional/GlobalTemperatures' # , - buttonText: 'College Admissions' # , reportName: 'College Admissions' # report: '/views/Regional/College' - # , - buttonText: 'Regional FlightDelays' # , reportName: 'Regional FlightDelays' # report: '/views/Regional/FlightDelays' config: # botToken: '111222333:AAO4L0Ttt1tt01-1TtT1t_t22tT' # tabcmd.exe tabcmdLocation: 'C:\Program Files\Tableau\Tableau Server\10.1\bin\' # reportsLocation: 'C:\Users\Administrator\Documents\bot\reports\' # logsLocation: 'C:\Users\Administrator\Documents\bot\logs\' admin: # chat id id: 198765432
スクリプトコード
# -*- coding: utf-8 -*- CONFIG_FILE = r'C:\Users\Administrator\Documents\bot\privacy.yaml' # API import telegram from telegram.ext import Updater from telegram.ext import MessageHandler, Filters from telegram.ext import CommandHandler import sys import subprocess from yaml import load import ast import os.path def updateSettings(): """ """ return load( file( CONFIG_FILE ) ) # config = updateSettings() # token = config['config']['botToken'] # tabcmd.exe tabcmdLocation = config['config']['tabcmdLocation'] # reportsLocation = config['config']['reportsLocation'] # logsLocation = config['config']['logsLocation'] def makeCustomKeyboard( userKeyboard ): """ . keyboard privacy.yaml. """ custom_keyboard = map( lambda z: [ telegram.KeyboardButton(x['buttonText']) for x in z ], userKeyboard ) return telegram.ReplyKeyboardMarkup(custom_keyboard, resize_keyboard='True') def logs(update, comment): """ . comment logs , chat id . """ u = ast.literal_eval(str(update)) with open( os.path.join(logsLocation, str(update.message.chat_id) + '.txt'), 'a') as f: f.write( str(u['message']['from']['username'].encode('utf-8')) + '\t' + str(u['message']['from']['first_name'].encode('utf-8')) + '\t' + str(u['message']['from']['last_name'].encode('utf-8')) + '\t' + str(u['message']['text'].encode('utf-8')) + '\t' + str(comment) + '\n') def start(bot, update): """ /start . ( privacy.yaml, users). , . """ # chat_id chat_id = update.message.chat_id # config = updateSettings() # if chat_id in config['users']: logs(update, 'Received /start command from user in privacy.yaml') # reply_markup = makeCustomKeyboard(config['users'][int(chat_id)]['keyboard']) bot.sendMessage(chat_id=chat_id, text=', ', reply_markup=reply_markup) logs(update, 'List of available reports sent') # else: logs(update, 'Received /start command from user NOT IN privacy.yaml') # bot.sendMessage(chat_id=chat_id, text=', . ' + \ ' , ') # u = ast.literal_eval(str(update)) bot.sendMessage(chat_id=config['admin']['id'], text=' ' + str(u['message']['from']['username'].encode('utf-8')) + ' ' + str(u['message']['from']['first_name'].encode('utf-8')) + ' ' + str(u['message']['from']['last_name'].encode('utf-8')) + ' ' + str(chat_id)) logs(update, 'Request for access sent') def echo(bot, update): """ , . , """ # chat_id chat_id=update.message.chat_id # response = update.message.text # config = updateSettings() # ( greenLight = True) greenLight = False # for line in config['users'][chat_id]['keyboard']: # for button in line: if button['buttonText'] == response: logs(update, 'Menu found, generating current keyboard and reports') # reply_markup = makeCustomKeyboard( config['users'][chat_id]['keyboard'] ) logs(update, 'Current keyboard generated') # greenLight = True # reportName = button['reportName'] reportAddress = button['report'] + '?:refresh=yes' if greenLight: logs(update, 'Starting to generate report') # ( ) bot.sendMessage(chat_id=chat_id, text=' , ...', reply_markup=reply_markup) logs(update, 'Message about report generation sent') # executeFile = os.path.join( tabcmdLocation, 'tabcmd.exe' ) # subprocess.call([ executeFile, 'login', '-s', 'localhost', '-u', 'admin', '-p', 'adminPassword']) # PDF subprocess.call([ executeFile, 'get', reportAddress, '-f', reportsLocation + reportName + '.pdf']) # subprocess.call([ executeFile, 'logout']) logs(update, 'Report generated, sending document') # bot.send_document(chat_id=chat_id, document=open(reportsLocation + reportName.encode('utf-8') + '.pdf', 'rb')) logs(update, 'Report sent') elif response == token: updater.stop() # , else: logs(update, 'Bad message, no access to this report') # reply_markup = makeCustomKeyboard(config['users'][chat_id]['keyboard']) bot.sendMessage(chat_id=chat_id, text=' . ' + \ ', admin@tableau.mycompany.ru ', reply_markup=reply_markup) logs(update, 'Main menu keyboard sent after bad message') # updater = Updater(token=token) dispatcher = updater.dispatcher updater.start_polling() # /start start_handler = CommandHandler('start', start) dispatcher.add_handler(start_handler) # echo_handler = MessageHandler([Filters.text], echo) dispatcher.add_handler(echo_handler)