 
      みなさんこんにちは。 準備されたレポートへのアクセスを提供することは、しばしば別の問題です。 管理のためのデータ処理結果への利便性と運用アクセスの問題が、それらのさらなる使用の運命を大きく左右します。 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)