たいくつなシフトキー Reprise

もういっかいはじめるメモ用紙

【2023-8-10更新】ニュース収集の代替が見つかるまで

Tweetdeckさんも使えなくってえ〜

でもまだRSSリーダーとか準備していなくってえ〜

そんならユーザースタイルシート書けばええやんみたいな気持ちになったので

  1. Chrometwitterのショートカットを作成する
  2. Adblock拡張機能に追加した chrome.google.com

  3. Stylusを拡張機能に追加した

chrome.google.com

@-moz-document domain("twitter.com") {
    aside[aria-label="認証を受ける"],
    aside[aria-label="おすすめユーザー"],
    div[data-testid="UserCell"],
    section[aria-labelledby="accessible-list-10"] h2,
    *[data-testid="left-impression-pixel"] + article
    {
        display:none;
    }
    .r-a023e6 {
        font-size:14px;
        line-height: 1.4;
    }
    .r-kzbkwu {
        padding-bottom: 4px;
    }
    .r-ttdzmv {
        padding-top: 8px;
    }
    .r-zl2h9q {
        margin-bottom: 0;
    }
    .css-1dbjc4n div[role="group"] {
        margin-top: 2px;
    }
    /*投稿部分*/
    .DraftEditor-root {
       font-size: 14px;
    }
}

2023-8-10 : 広告の出され方が変わってたので更新

TogglのログをGoogleカレンダーにぶちこみたい(GASで)

社内を工数Googleカレンダー上で管理したいというお達しが届き

chatGPT先生に相談しながら作った。

もしGASが初めての人はできればテスト用のカレンダーを作って、試してからのがいいかもしれない。

※2023/7/7 重複しまくったので改修

トリガーで1日1回で回す用

最初全部取得で重複を見るようにしたかったが日時のフォーマットを比較するのがだるすぎて諦め。

実行から24時間だけ遡って反映するようにした。

トリガーは一番仕事してなさそうな時間に指定するのがよい。

実行の段階でタイマーが動いてると最新の時間エントリがエラーになるので悲しくなると思う。

function syncTogglToCalendar() {
  var togglApiKey = 'YOUR_TOGGL_API_KEY';  // https://track.toggl.com/profile の API Tokenから取得
  var calendarId = 'YOUR_CALENDAR_ID';  // 該当のカレンダーのID

  var togglTimeEntries = fetchTogglTimeEntries(togglApiKey);
  var calendarEvents = getCalendarEvents(calendarId);

  var now = new Date();
  var pastStartTime = new Date(now.getTime() - (24 * 60 * 60 * 1000));

  // Togglの時間エントリをカレンダーに反映
  for (var i = 0; i < togglTimeEntries.length; i++) {
    var timeEntry = togglTimeEntries[i];
    var timeEntryStartTime = new Date(timeEntry.start);
    var timeEntryEndTime = new Date(timeEntryStartTime.getTime() + timeEntry.duration * 1000);

    // タイムエントリの開始時間が24時間前よりも後の場合にのみカレンダーに新しいイベントを作成
    if (timeEntryStartTime > pastStartTime && timeEntryStartTime <= now) {
      // カレンダーに新しいイベントを作成
      var event = createCalendarEvent(calendarId, timeEntry.description, timeEntryStartTime, timeEntry.duration);

      // イベントの詳細情報を設定
      event.setDescription(timeEntry.description);
      event.setLocation(timeEntry.project);

      Logger.log('Created event: ' + event.getTitle());
    }
  }
}

// Togglから時間エントリを取得
function fetchTogglTimeEntries(apiKey) {
  var url = 'https://api.track.toggl.com/api/v8/time_entries';
  var headers = {
    'Authorization': 'Basic ' + Utilities.base64Encode(apiKey + ':api_token')
  };

  var options = {
    'headers': headers,
    'method': 'GET'
  };

  var response = UrlFetchApp.fetch(url, options);
  var data = JSON.parse(response.getContentText());

  return data;
}

// カレンダーからイベントを取得
function getCalendarEvents(calendarId) {
  var calendar = CalendarApp.getCalendarById(calendarId);
  var today = new Date();
  var tomorrow = new Date();
  tomorrow.setDate(today.getDate() + 1); // 現在の日付から1日後の日付を取得

  var events = calendar.getEvents(today, tomorrow);
  return events;
}

// カレンダーに新しいイベントを作成
function createCalendarEvent(calendarId, title, startTime, duration) {
  var calendar = CalendarApp.getCalendarById(calendarId);

  var end = new Date(startTime.getTime() + duration * 1000); // 秒をミリ秒に変換して終了時間を計算

  var event = calendar.createEvent(title, startTime, end);
  return event;
}

まるごと全部取得して反映する用

今までTogglで取得してたけど、全部遡って反映したい時用。*1

これを1日1回ずつトリガーで実行しちゃうと、ポケット叩いたビスケットみたいにどんどん増えるので注意。

function syncTogglToCalendar() {
  var togglApiKey = 'YOUR_TOGGL_API_KEY';  // https://track.toggl.com/profile の API Tokenから取得
  var calendarId = 'YOUR_CALENDAR_ID';  // 該当のカレンダーのID

  var togglTimeEntries = fetchTogglTimeEntries(togglApiKey);
  var calendarEvents = getCalendarEvents(calendarId);

  // Togglの時間エントリをカレンダーに反映
  for (var i = 0; i < togglTimeEntries.length; i++) {
    var timeEntry = togglTimeEntries[i];

    // 同じタイトルと開始時間を持つカレンダーイベントが存在するか確認
    var existingEvent = findExistingEvent(calendarEvents, timeEntry.description, timeEntry.start);

    if (existingEvent) {
      // 既存のイベントが見つかった場合はスキップ
      continue;
    }

    // カレンダーに新しいイベントを作成
    var event = createCalendarEvent(calendarId, timeEntry.description, timeEntry.start, timeEntry.duration);

    // イベントの詳細情報を設定
    event.setDescription(timeEntry.description);
    event.setLocation(timeEntry.project);

    Logger.log('Created event: ' + event.getTitle());
  }
}

// Togglから時間エントリを取得
function fetchTogglTimeEntries(apiKey) {
  var url = 'https://api.track.toggl.com/api/v8/time_entries';
  var headers = {
    'Authorization': 'Basic ' + Utilities.base64Encode(apiKey + ':api_token')
  };

  var options = {
    'headers': headers,
    'method': 'GET'
  };

  var response = UrlFetchApp.fetch(url, options);
  var data = JSON.parse(response.getContentText());

  return data;
}

// カレンダーからイベントを取得
function getCalendarEvents(calendarId) {
  var calendar = CalendarApp.getCalendarById(calendarId);
  var today = new Date();
  var tomorrow = new Date();
  tomorrow.setDate(today.getDate() + 1); // 現在の日付から1日後の日付を取得

  var events = calendar.getEvents(today, tomorrow);
  return events;
}

// 既存のイベントを検索
function findExistingEvent(events, title, startTime) {
  for (var i = 0; i < events.length; i++) {
    var event = events[i];

    if (event.getTitle() === title && event.getStartTime().getTime() === startTime) {
      return event;
    }
  }

  return null;
}

// カレンダーに新しいイベントを作成
function createCalendarEvent(calendarId, title, startTime, duration) {
  var calendar = CalendarApp.getCalendarById(calendarId);
  
  var start = new Date(startTime); // 開始時間をDateオブジェクトとしてパース
  var end = new Date(start.getTime() + duration * 1000); // 秒をミリ秒に変換して終了時間を計算

  var event = calendar.createEvent(title, start, end);
  return event;
}

工数管理はたいへんだと思うけど

部署によって仕事の細切れ具合も、ブロック化する塩梅も違うから

社内で共通の言語で語ることは難しいね

楽できるところは楽をしながら

お互い様でやっていきたいものです

*1:たぶんこれは全部は遡らないはず