Month: July 2021

  • [บันทึกกันลืม] วิธีแก้ปัญหาข้อมูลประเภท timedelta64[ns] ใน Pandas ไม่สามารถเขียนลงฐานข้อมูล field ที่เป็น Time ได้

    เหตุ:

    import pymysql
    import pandas as pd
    import sqlalchemy
    
    import time
    import datetime
    
    conn = pymysql.connect(
            host="source.database.server",
            port=3306,
            user='username',
            password='password',
            database='databasename',
        )
    
    sql="""
       SELECT *
       FROM   table1
    """
    df1=pd.read_sql(sql,conn)
    df1.dtypes

    ผลคือ:

    .
    .
    .
    ref_visit_date                            object
    ref_visit_time                   timedelta64[ns]
    .
    .
    .
    

    ซึ่ง ref_visit_time นั้น ใน MySQL/MariaDB ใช้ชนิดเป็น Time

    เช่น 08:00:00 หมายถึง 8 นาฬิกา อะไรทำนองนั้น

    ปัญหา:

    อยู่ที่ตอนเอา Dataframe นี้ ไป Write ใส่อีก Table นึง

    host="destination.database.server"
    port=int(3306)
    user='user'
    password='password'
    dbname='databasename'
    db_string = f"mysql+pymysql://{user}:{password}@{host}:{port}/{dbname}"
    
    destination_conn = sqlalchemy.create_engine(db_string)
    
    df.to_sql('table2'
           , con=destination_conn
           , if_exists='append'
           , index=False
           , method='multi'
           , chunksize=10000)

    ซึ่ง table2 นั้น มีโครงสร้างเหมือนกับ table1 เลย โดยเฉพาะ ref_visit_time มีชนิดเป็น Time เช่นกัน

    แต่ถ้า run code นี้จะได้ Error/Warning ว่า

    UserWarning: the 'timedelta' type is not supported, and will be written as integer values (ns frequency) to the database.

    เหตุเพราะ แทนที่จะเก็บเป็น Time มันดันเปลี่ยนเป็น Integer ที่เป็นจำนวน Nanosecond แทนนั่นเอง

    วิธีแก้ไข

    ต้องตรวจสอบว่า มี column ใน destination table มีชนิดเป็น Time (timedelta64[ns]) ให้เอาไปบวกกับเวลาเริ่มต้น แล้ว เปลี่ยนชนิดเป็น Time แทน ดังนี้

    for column in df:
        if df[column].dtype == 'timedelta64[ns]':
            df[column]=df[column].apply(lambda x: (datetime.datetime.min+x).time())

    เราก็จะได้ข้อมูลที่ถูกต้องกลับมา

    ตามนั้นครับ

  • Zoom Developer – การใช้ Webhook เพื่อรายงานเหตุการณ์ต่าง ๆ ในห้อง Zoom

    เช่นเดียวกับ Enterprise-grade อื่น ๆ Zoom ก็มี API ให้เราพัฒนาโน่นนี่ได้ บทความนี้จะมาแนะนำวิธีการ Webhook เพื่อรายงาน ผ่าน LINE Notify เมื่อมีคนเข้ามาในห้อง เช่นใช้เพื่อแจ้งคนบน Host ว่า มีคนเข้ามาแล้วนะ เป็นต้น

    แต่ก่อนอื่น ต้องเข้าใจว่า Zoom Account มี หลายรูปแบบ โดยเข้าไปที่เว็บ

    https://zoom.us/profile

    1. Basic Account อันนี้ หลายคนคงจะใช้อยู่ ที่ถูกลิมิต ไม่ให้ใช้งานเกิน 40 นาที — อันนี้ จะเห็นคำว่า BASIC อยู่ในหน้า Profile ดังรูปที่ 1
    รูปที่ 1. Basic Account

    2. LICENSED Account แบบนี้ สร้างเอง จ่ายตังค์เอง นักเลงพอ ก็จะประชุมได้ไม่จำกัดเวลา คนเข้าได้พร้อมกัน 100 คน จะมีคำว่า LICENSED ดังรูปที่ 2

    รูปที่ 2. Licensed Account

    3. แต่มีอีกแบบ ไฮโซกว่า คือแบบ Corporate (มั้ง) แบบว่า ในองค์กรซื้อ ข้อแตกต่างกับแบบที่ 2 คือ ประชุมไม่จำกัดเวลา และ ผู้เข้าร่วมได้สูงสุด 300 คน ดังรูปที่ 3

    รูปที่ 3. Corporate Licensed Account

    คราวนี้ เชื่อว่าหลายคนอาจจะยังไม่ทราบว่า เราสามารถเขียนโปรแกรมเพื่อจัดการงานต่าง ๆ กับ Zoom ได้ โดยไปที่เว็บ

    https://marketplace.zoom.us/develop/create

    สำหรับ Basic Account เค้าให้เราเป็น Admin จึงสร้างได้ครบทุกชนิด ดังรูปที่ 4

    รูปที่ 4. Basic Account สร้างได้หมดทุกอย่าง

    สำหรับ Licensed Account แบบจ่ายตังค์เอง เค้าให้เราเป็น Admin จึงสร้างได้ครบทุกชนิด ดังรูปที่ 5

    รูปที่ 5. Licensed Account สร้างได้หมดทุกอย่าง

    ส่วน Corporate Licensed Account … ก็น่าเสียดาย ที่ Admin เค้าให้เราเป็นแค่ Member จึงไม่สามารถใช้งานได้ครบถ้วนได้ เสียดายตังค์ เอ๊ย เสียดายจัง ดังรูปที่ 6

    รูปที่ 6. Corporate Licensed Account สร้างได้เฉพาะ OAuth กับ Chatbot เพราะเค้าให้เราเป็นแค่ Member

    ก็ … แล้วแต่นะ

    มาสร้าง Zoom Webhook กันเถอะ

    Requirement คือ เราเป็น Host เปิดห้อง Zoom เอาไว้ ซึ่งจะเริ่มประชุมเวลา 10:00 แต่ต้องการทราบว่า มีใครเข้ามาก่อนเวลา ให้ ส่ง Line Notify ไปแจ้ง Host ให้ทราบ

    Zoom Webhook จะทำหน้าที่เฝ้าห้องให้ แล้วเมื่อเกิด Event ที่กำหนด ก็จะส่ง POST request ไปยัง URL ที่กำหนดไว้ ดังนั้น สิ่งแรกคือ เราจะมาสร้าง Google Cloud Function ด้วยภาษา Python เพื่อรับ POST Request นั้น

    (Prerequisite: ท่านสามารถใช้ Google Cloud Platform และ LINE Notify ได้แล้ว)

    Google Cloud Function

    1. ไปที่ https://console.cloud.google.com/functions/add จะได้หน้าตาประมาณนี้ (รูปที่ 7)
      กรอก Function name, Region (แนะนำให้ใช้ Singapore), ให้ Trigger ด้วย HTTP Protocol และ Allow unauthenticated invocation. จากนั้นคลิก Save แล้วก็ Next
    รูปที่ 7. สร้าง Google Cloud Function
    1. เลือก Runtime เป็นภาษา programming ที่ต้องการ ในที่นี้จะเลือก Python แล้วคลิกที่ปุ่ม ​Enable API ตามรูปที่ 8.
    รูปที่ 8. เลือก Python แล้ว Enable API (สำหรับการใช้งานครั้งแรก)
    1. ใส่ Code ดัง รูปที่ 9 (สามารถ Copy จาก gist : https://gist.github.com/nagarindkx/fe36a26bd867d1ae627ad0d69f6e6b4d)

    ในบรรทัดที่ 3: เดี๋ยวเราจะเอากลับมาใส่ในภายหลัง

    ในบรรทัดที่ 4: ต้องไปสร้าง LINE Notify Token ก่อน สามารถทำตามวิธีการนี้ได้ วิธีแจ้งเตือนจาก Google Forms เข้า LINE

    ในบรรทัดที่ 7 และ 8: เราจะกลับมาสลับ Comment ในภายหลัง

    รูปที่ 9. Python code สำหรับรับการ Alert จากฝั่ง Zoom Webhook

    สุดท้าย แก้ไขไฟล์ requirements.txt เพิ่มบรรทัดใหม่ แล้วเขียนคำว่า

    requests

    เข้าไป ตรงนี้จะเป็น packages ไว้ใช้ติดต่อเพื่อส่ง LINE Notify ดังรูปที่ 10.

    จากนั้นคลิกปุ่ม DEPLOY

    รูปที่ 10. แก้ไขไฟล์ requirements.txt เพิ่ม requests package เข้าไปด้วย เพื่อให้สามารถเรียก LINE Notify API ได้

    ก่อนจะทำขั้นตอนถัดไป ให้คลิกที่ Tab TRIGGER แล้ว copy Trigger URL ไว้ ดัง รูปที่ 11

    รูปที่ 11. copy Trigger URL เก็บไว้ก่อน

    Zoom Webhook Only

    ต่อไป กลับมาที่ Zoom App Marketplace (https://marketplace.zoom.us/develop/create)

    คลิกที่ ปุ่ม Create ใน Webhook Only

    ระบบจะเด้งให้ตั้งชื่อ App Name ดังรูปที่ 12.

    ให้ตั้งชื่อตามสมควร แล้วคลิกปุ่ม Create

    รูปที่ 12. ตั้งชื่อ App Name

    ตั้งค่าต่าง ๆ ดังรูปที่ 13. แล้วคลิกปุ่ม Continue

    รูปที่ 13. กรอข้อมูลต่าง ๆ

    ต่อไป เป็นขั้นตอนการเฝ้า Event หรือ Event Subscriptions

    คลิก Switch

    คลิกปุ่ม Add new event subscription

    กรอกข้อมูล Subscription Name

    แล้วเอา Trigger URL จาก รูปที่ 11. ใส่ใน Event notification endpoint URL

    ดังรูปที่ 14.

    รูปที่ 14. ระบุ Subscription Name และ Event notification endpoint URL

    จากนั้น คลิกปุ่ม Add events

    เลือก Event types ที่ต้องการ ในที่นี้ เป็น Participant joined meeting before host ดังรูปที่ 15

    จากนั้น คลิกปุ่ม Done แล้ว Save

    รูปที่ 15. เลือก Participant joined meeting before host

    จากนั้น ระบบจะให้ Verification Token มา ให้ copy เก็บไว้ เพื่อเอาไปใส่ใน Google Cloud Function ต่อไป ดังรูปที่ 16.

    จากนั้นคลิกปุ่ม Continue เป็นอันเรียบร้อย

    รูปที่ 16. Verification Token เพื่อเอาไปใส่ใน Google Cloud Function

    สุดท้าย กลับไปที่ Google Cloud Function

    • กลับเอา Verification Token ไปใส่ใน zoom_verification_token
    • เอา LINE Notify Token ของจริง ไปใส่ใน access_token
    • Uncomment บรรทัดที่ 7
    • Comment บรรทัดที่ 8

    แล้วคลิก Deploy

    ทดสอบใช้งาน

    สร้างห้อง Zoom แบบไม่ต้องมี Waiting Room ลองให้คนอื่นเข้าไปในห้องก่อน Host

    Zoom Webhook จะส่ง HTTP POST ไปยัง Google Cloud Function โดยจะใส่ค่าลงไปใน Header “authorization”

    ถ้า ค่าดังกล่าว ตรงกับ zoom_verification_token ระบบก็จะส่ง LINE Notify ออกไป

    หวังว่าจะเป็นประโยชน์ครับ

  • [บันทึกกันลืม] Pandas Dataframe กับการขึ้นบรรทัดใหม่ ชิดซ้าย และทำให้คำที่ค้นหา เป็นตัวหนาสีแดง

    from IPython.display import display, HTML
    finding='text to find'
    display(HTML(df1.to_html()
                 .replace('\\r\\n','<br>')
                 .replace('<td>','<td style="text-align: left; vertical-align: top;">')
                 .replace('<th>','<th style="text-align: left;">')
                 .replace(f'{finding}',f'<b style="color:red;">{finding}</b>')
                )
           )

    กันลืมไง สั้น ๆ