質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

GoogleCalendarAPIを用いてDiscordからカレンダーを操作するBotの作成

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 870

Arisa.Sunagawa

score 15

PythonによるGoogleカレンダーの削除

目的:discordにて何らかの投稿があったときに、投稿内の日付を取得しカレンダーを操作する。
現在の目標:固定の日付、名前のカレンダーイベントを追加/削除する
状態:service.events().delete(calendarId=self.__CARENDAR_ID,eventId=eventid.execute()にてカレンダーの削除に失敗する。

発生している問題・エラーメッセージ

Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\[User名]\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\client.py", line 255, in _run_event
    await coro(*args, **kwargs)
  File "C:\Users\[User名]\Desktop\Bot\2\main.py", line 111, in on_message
    calendar.del_calendar_event('test2', '2019-05-11T21:00:00+09:00', '2019-05-11T23:00:00+09:00')
  File "C:\Users\[User名]\Desktop\Bot\2\google_calendar.py", line 98, in del_calendar_event
    eventId=eventid
  File "C:\Users\[User名]\AppData\Local\Programs\Python\Python37-32\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "C:\Users\[User名]\AppData\Local\Programs\Python\Python37-32\lib\site-packages\googleapiclient\http.py", line 851, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/calendar/v3/calendars/[GoogleID]%40gmail.com/events/MmFjbXMwZWVrbnFxMXNiZm0yMzRkdjlxMWsgZGlnaXRhbGxpYnJhcnlmb3JtZUBt? returned "Not Found">

該当のソースコード

カレンダー操作クラス

import datetime
import pickle
import re
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

class google_calendar:
    # カレンダーへのRW権限(スコープ)を変更する
    # 変更する際はtoken.pickleを削除すること
    __SCOPES = ['https://www.googleapis.com/auth/calendar']

    # 変更する対象のカレンダー
    __CARENDAR_ID = '[カレンダーID]'

    # 東京でのUTCとの誤差
    __ERR_UTC_TOKYO = 9

    # 時間の出力フォーマット
    __FORMAT_TIME = '%Y-%m-%dT%H:%M:%S%z'

    def __init__(self):#インスタンス変数管理
        pass

    def connect(self):
        ''' # token.pickleを初期作成する際は外すこと。
        creds = None
        # token.pickleファイルには、ユーザーのアクセストークンと更新トークンが格納されています。
        # 許可フローが最初に完了したときに自動的に作成されます。

        # token.pickleの読み込み
        if os.path.exists('token.pickle'):
            with open('token.pickle', 'rb') as token:
                creds = pickle.load(token)

        # token.pickleの読み込み失敗時
        # 利用可能な(有効な)認証情報がない場合は、ユーザーにログインさせます。
        if not creds or not creds.valid:
            ## ここ何の処理?
            if creds and creds.expired and creds.refresh_token:
                # ブラウザのリフレッシュ
                creds.refresh(Request())

            # ブラウザで認証URLを開く
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    'credentials.json', SCOPES)
                creds = flow.run_local_server()

            # 次回の実行のために資格情報を保存します
            with open('token.pickle', 'wb') as token:
                pickle.dump(creds, token)
        '''

        # token.pickleの読み込み'(token.pickleを作成する際はコメントアウトすること)
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)

        # カレンダーAPIとの接続
        service = build('calendar', 'v3', credentials=creds)

        return service

    def add_calendar_event(self, summary, start_time, end_time):
        # APIとの接続
        service = self.connect()

        # カレンダ情報の格納
        body = {'summary': summary,
                'start': {  'dateTime': start_time,
                            'timeZone': 'Asia/Tokyo',
                         },
                'end':   {  'dateTime': end_time,
                            'timeZone': 'Asia/Tokyo',
                         },
                'attendees': '',
               }

        # カレンダへイベントの追加
        event = service.events().insert(
            calendarId=google_calendar.__CARENDAR_ID,
            body=body
        ).execute()

    def del_calendar_event(self, summary, start_time, end_time):
        # APIとの接続
        service = self.connect()

        # イベントIDの取得
        eventid = self.get_calendar_event(summary, start_time, end_time)

        print(eventid)

        # カレンダのイベントを削除
        service.events().delete(
            calendarId=self.__CARENDAR_ID,
            eventId=eventid
        ).execute()

    def get_calendar_event(self, summary, start_time, end_time):
        # APIとの接続
        service = self.connect()

        eventid = 0
        page_token = None

        # カレンダーの取得
        while True:
            events = service.events().list(
                calendarId=google_calendar.__CARENDAR_ID,
                pageToken=page_token
            ).execute()

            # 日付データ文字(引数)を置換
            startTime = datetime.datetime.strptime(start_time,self.__FORMAT_TIME)
            endTime = datetime.datetime.strptime(end_time,self.__FORMAT_TIME)

            # イベントの検索
            for event in events['items']:
                start = event['start']
                end   = event['end']

                # 日付と卓名が一致したら、それを返却
                if event['summary'] == summary and datetime.datetime.strptime(start['dateTime'],self.__FORMAT_TIME) == startTime and datetime.datetime.strptime(end['dateTime'],self.__FORMAT_TIME) == endTime:
                    temp = event['htmlLink'].split('eid=')
                    eventid = temp[1]
                    break

            # 次イベントの取得
            page_token = events.get('nextPageToken')

            # 読むイベントがなくなったら終了
            if not page_token:
                break

        # idの返却
        return eventid


メイン関数

import discord
import re
import dicebot

### 自作サブルーチンファイル ###
import google_calendar

### 定数宣言 ###
# BOTのトークン
TOKEN = '[BOTトークン]'

if __name__ == '__main__':

    # クラスの呼び出し
    calendar = google_calendar.google_calendar()
    client = discord.Client()

    # 起動時のイベントハンドラ
    @client.event
    async def on_ready():
        print('Logged in as')
        print(client.user.name)
        print(client.user.id)
        print('------')

    ### Botへのコマンド送信時の動作 ###
    @client.event
    async def on_message(message):
        com = message.content

        # カレンダー系(試験用)
        elif re.match('\$cadd1', com):
            calendar.add_calendar_event('test', '2019-05-11T21:00:00', '2019-05-11T23:00:00')
            send_ms = 'カレンダーを追加'
            await message.channel.send(send_ms)

        elif re.match('\$cadd2', com):
            calendar.add_calendar_event('test2', '2019-05-11T21:00:00', '2019-05-11T23:00:00')
            send_ms = 'カレンダーを追加'
            await message.channel.send(send_ms)

        elif re.match('\$cdel', com):
            calendar.del_calendar_event('test2', '2019-05-11T21:00:00+09:00', '2019-05-11T23:00:00+09:00')
            send_ms = 'カレンダーを削除'
            await message.channel.send(send_ms)

        elif re.match('\$csearch', com):
            send_ms = calendar.get_calendar_event('test2', '2019-05-11T21:00:00+09:00', '2019-05-11T23:00:00+09:00')
            await message.channel.send(send_ms)

    client.run(TOKEN)

試したこと

1.discordにて$cadd1,$cadd2を入力し、カレンダーイベントを2つ追加する
2.$csearchを入力し、カレンダーイベントのIDを取得する。
3.$cdelを入力し、対象のカレンダーを削除する。

このとき追加/特定カレンダーイベントの取得までは行えたのですが、削除が行えなず困っています。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

delに渡すイベントIDはhyperlinkではなくidでした。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る