|
// Chrome 132 相当で動作確認 |
|
// 新しめのブラウザでないと動作しません |
|
|
|
// 取得したいチャットルームのルームID。先頭のridを除いた数字のみ。 |
|
// [] を指定すると、アクセスできる全ルームの情報をダウンロードします。 |
|
var TARGET_ROOM_IDS = [] |
|
// var TARGET_ROOM_IDS = [123456789, 987654321] |
|
|
|
// 取得したくないチャットルームのルームID。 |
|
// ログ用ルーム等のダウンロードを除外するのに利用します |
|
var EXCEPT_ROOM_IDS = [] |
|
// var EXCEPT_ROOM_IDS = [123456789] |
|
|
|
// 通信間隔[ミリ秒]。ダウンロードするデータの規模が大きい場合は、1000(1秒)ぐらいに指定してください。 |
|
var INTERVAL_TIME = 300; |
|
|
|
// チャットワークのホスト. 企業用の場合は適宜修正ください |
|
var HOST_URL = "www.chatwork.com" |
|
// var HOST_URL = "kcw.kddi.ne.jp" |
|
|
|
// カスタマイズ1:各メッセージデータにYYYY/MM/DD HH:MM:SS形式の時刻を追加する |
|
var APPEND_DATE = true |
|
|
|
// カスタマイズ2:各メッセージデータに、発言者のユーザー名を追加する(標準ではアカウントIDのみ) |
|
var APPEND_USERNAME = true |
|
|
|
// カスタマイズ3:リアクション情報を削除する(不要な人もいるようなので) |
|
var DELETE_REACTIONS = false |
|
|
|
// カスタマイズ4: 添付ファイルをダウンロードする |
|
var DOWNLOAD_ATTACHMENTS = true |
|
|
|
//==================================== |
|
// ここ以降は修正不要 |
|
|
|
var debug = false |
|
var token = ACCESS_TOKEN |
|
var myid = MYID |
|
|
|
if(debug === false){ |
|
console.debug = () => {} |
|
} |
|
|
|
async function sleep(ms){ |
|
return new Promise(resolve => setTimeout(resolve, ms)); |
|
} |
|
|
|
async function do_fetch({url, formData}){ |
|
const _formData = new FormData(); |
|
Object.entries(formData).forEach(([key, value]) => { |
|
_formData.append(key, value) |
|
}) |
|
const resp = await fetch(url, { |
|
method: 'POST', |
|
mode: 'cors', |
|
cache: 'no-cache', |
|
credentials: 'same-origin', |
|
redirect: 'follow', |
|
referrerPolicy: 'same-origin', |
|
body: _formData, |
|
}) |
|
return resp |
|
} |
|
|
|
async function saveAs(filename, content){ |
|
console.debug("START saveAs", filename, content) |
|
|
|
let blob |
|
if(typeof content === 'string'){ |
|
console.debug("content is String") |
|
blob = new Blob([content], { |
|
type: "application/force-download" |
|
}) |
|
} else if(content instanceof Blob){ |
|
console.debug("content is Blob") |
|
// type変更のために詰め替えることで、タブを開かせずに確実にダウンロードさせる |
|
blob = new Blob([ content ], { |
|
type: "application/force-download" |
|
}) |
|
} else { |
|
console.debug("content is object") |
|
blob = new Blob([ JSON.stringify(content, null, 2) ], { |
|
type: "application/force-download" |
|
}) |
|
} |
|
|
|
console.debug(" download blob", blob) |
|
const url = URL.createObjectURL(blob) |
|
const link = document.createElement('a') |
|
link.href = url |
|
link.dataType = "binary"; |
|
link.download = filename |
|
link.click() |
|
link.remove() |
|
setTimeout(() => { |
|
URL.revokeObjectURL(url); |
|
}, 1E4); |
|
} |
|
|
|
async function init_load() { |
|
console.debug("START init_load") |
|
const url = `https://${HOST_URL}/gateway/init_load.php?myid=${myid}&_v=1.80a&_av=5&ln=en&rid=0&with_unconnected_in_organization=1` |
|
const resp = await do_fetch({ |
|
url: url, |
|
formData: { |
|
'pdata': JSON.stringify({ |
|
_t: token, |
|
}) |
|
}, |
|
}) |
|
return resp.json() |
|
} |
|
|
|
async function get_account_info(aids){ |
|
console.debug("START get_account_info", aids) |
|
const url = `https://${HOST_URL}/gateway/get_account_info.php?myid=${myid}&_v=1.80a&_av=5&ln=en&get_private_data=0` |
|
const resp = await do_fetch({ |
|
url: url, |
|
formData: { |
|
'pdata': JSON.stringify({ |
|
"aid": aids, |
|
"_t":token, |
|
}) |
|
}, |
|
}) |
|
return resp.json() |
|
} |
|
|
|
async function load_chat(rid){ |
|
console.debug("START load_chat", rid) |
|
const url = `https://${HOST_URL}/gateway/load_chat.php?myid=${myid}&_v=1.80a&_av=5&ln=en&room_id=${rid}&last_chat_id=0&unread_num=0&bookmark=1&file=1&desc=1` |
|
const resp = await do_fetch({ |
|
url: url, |
|
formData: { |
|
'pdata': JSON.stringify({ |
|
"load_file_version":"2", |
|
"_t": token, |
|
}) |
|
}, |
|
}) |
|
return resp.json() |
|
} |
|
|
|
// first_chat_id よりも古い(chat_idが小さい)メッセージを取得する(first_chat_idは含まない) |
|
// first_chat_id == 0 のときはidが昇順で、そうでない場合はidが降順で返ってくる |
|
// 1回のリクエストで40メッセージまで |
|
async function load_old_chat(rid, first_chat_id){ |
|
console.debug("START load_old_chat", rid, first_chat_id) |
|
const url = `https://${HOST_URL}/gateway/load_old_chat.php?myid=${myid}&_v=1.80a&_av=5&ln=en&room_id=${rid}&first_chat_id=${first_chat_id}` |
|
const resp = await do_fetch({ |
|
url: url, |
|
formData: { |
|
'pdata': JSON.stringify({ |
|
_t: token, |
|
}) |
|
}, |
|
}) |
|
return resp.json() |
|
} |
|
|
|
async function get_attachment_as_blob(file_id){ |
|
console.info("START get_attachment_as_blob", file_id) |
|
const resp = await fetch(`https://${HOST_URL}/gateway/download_file.php?bin=1&file_id=${file_id}&preview=0`) |
|
return resp.blob() |
|
} |
|
|
|
async function get_messages(room_id) { |
|
console.info("START get_messages", room_id) |
|
const sort_by_id = (a,b) => { return Number(a.id) - Number(b.id) } // 昇順 |
|
let messages = [] |
|
let oldest_msg_id = 0 |
|
do { |
|
console.info(" DO-WHILE-LOOP oldest_msg_id: ", oldest_msg_id) |
|
const load_old_chat_json = await load_old_chat(room_id, oldest_msg_id) |
|
load_old_chat_json.result.chat_list.sort(sort_by_id) |
|
messages.unshift(...load_old_chat_json.result.chat_list) |
|
oldest_msg_id = load_old_chat_json.result.chat_list?.[0]?.id |
|
await sleep(INTERVAL_TIME) |
|
} while(oldest_msg_id !== undefined) |
|
|
|
return messages |
|
} |
|
|
|
async function customize_messages(messages, aids){ |
|
|
|
const yyyymmddhhmmss = new Intl.DateTimeFormat( |
|
undefined, |
|
{ |
|
year: 'numeric', |
|
month: '2-digit', |
|
day: '2-digit', |
|
hour: '2-digit', |
|
minute: '2-digit', |
|
second: '2-digit', |
|
fractionalSecondDigits: undefined, |
|
} |
|
) |
|
|
|
for(const message of messages){ |
|
if(APPEND_DATE){ |
|
message.datetime = yyyymmddhhmmss.format(new Date(message.tm * 1000)) |
|
} |
|
|
|
if(APPEND_USERNAME){ |
|
message.aid_name = aids.result.account_dat[message.aid].name || "ユーザー名情報なし" |
|
} |
|
|
|
if(DELETE_REACTIONS){ |
|
delete message.reactions |
|
} |
|
} |
|
} |
|
|
|
async function downloadChatRoom(room_id){ |
|
console.debug("START downloadChatRoom", room_id) |
|
|
|
// チャットルーム情報を取得 |
|
{ |
|
const load_chat_json = await load_chat(room_id) |
|
await saveAs(`${room_id}_load_chat.json`, load_chat_json) |
|
} |
|
|
|
{ |
|
// 全メッセージを取得 |
|
console.debug("get_messages") |
|
const messages = await get_messages(room_id) |
|
|
|
// チャット内で発言したすべてのメンバーの情報を取得・保存 |
|
console.debug("get_account_info") |
|
const aids = messages |
|
.reduce((prev, message) => { |
|
return prev.add(message.aid) |
|
}, new Set()) |
|
const account_info_json = await get_account_info([...aids]) |
|
await saveAs(`${room_id}_account_info.json`, account_info_json) |
|
|
|
// メッセージのカスタマイズ(日付時刻付与など) |
|
customize_messages(messages, account_info_json) |
|
console.debug(messages) |
|
|
|
// メッセージの保存 |
|
await saveAs(`${room_id}_messages.json`, messages) |
|
} |
|
|
|
// 全添付ファイルをダウンロード |
|
if (DOWNLOAD_ATTACHMENTS) { |
|
console.debug("get_attachment") |
|
const load_chat_json = await load_chat(room_id) |
|
await saveAs(`${room_id}_load_chat.json`, load_chat_json) |
|
for(const file of load_chat_json.result?.file_list){ |
|
const file_id = file.id |
|
const file_name = `${room_id}_${file_id}_${file.fn}` |
|
await saveAs(file_name, await get_attachment_as_blob(file_id)) |
|
await sleep(INTERVAL_TIME) |
|
} |
|
} |
|
} |
|
|
|
|
|
async function downloadChatRooms(){ |
|
console.debug("START downloadChatRooms") |
|
const init_load_json = await init_load() |
|
await saveAs("init_load.json", init_load_json) |
|
|
|
for(const [room_id, room_obj] of Object.entries(init_load_json.result.room_dat)){ |
|
console.debug(1, "FOR-LOOP downloadChatRooms: ", room_id, room_obj) |
|
|
|
const room_name = room_obj?.n |
|
|| Object.entries(init_load_json.result?.contact_dat)?.filter(([k,v]) => v.rid == room_id)?.[0]?.[1]?.name |
|
|| "ルーム名なし" |
|
|
|
if( |
|
(EXCEPT_ROOM_IDS.includes(Number(room_id))) || |
|
(TARGET_ROOM_IDS.length !== 0 && !TARGET_ROOM_IDS.includes(Number(room_id))) |
|
){ |
|
console.log("skip: ", room_id, room_name) |
|
continue |
|
} |
|
|
|
console.log("downloading: ", room_id, room_name) |
|
|
|
// わかりやすさのため、ルーム名の空ファイルを作成 |
|
await saveAs(`${room_id}_${room_name}.txt`, " ") |
|
|
|
await downloadChatRoom(room_id) |
|
} |
|
} |
|
|
|
await downloadChatRooms() |