CLASSAPI/list
from CLASSのお知らせを取得する方法を探
CLASSのお知らせを取得するscript
ScrapboxのUserScriptから使える
要ScrapboxからCLASSのページにアクセスするUserScript
2021-04-05 20:20:35 ↓を実装した
カテゴリごとに取得するように変更した
2021-03-21
01:55:52 仕様を変更する
CLASSのお知らせの本文の取得機能を削る
CLASSのsessionは時間制限があるので、本文まで取得していると時間がかかりすぎてlog outされてしまう
log inから一度に行うようにする
2021-02-24 13:51:27 改ページしているお知らせページにも対応した
あとは、本文も取得する処理も入れるか。
未読の本文のみ取得する
dependencies
CLASSAPI/login
CLASSのお知らせの詳細ページを操作するscript
code:script.js
import {login} from '../CLASSAPI%2Flogin/auth.js';
import {parseAnnounce} from './announce.js';
import {goDetailedInfoPage, goNext} from '../CLASSのお知らせの詳細ページを操作するscript/script.js';
全てのお知らせの一覧を取得する
やめた。カテゴリごとに取得するように変える
全部取得すると時間がかかる
Vercelの時間制限内で処理が終わらない
code:script.js
const nextButtonId = 'form1:Poa00201A:htmlParentTable:htmlDetailTbl2:deluxe1__pagerNext';
export async function getAnnounceList(categoryId, {userId, password}) {
const {html, announceSummary, comSunFacesVIEW} = await login({userId, password});
const {hasHiddenAnnounces} = announceSummary.find(({id}) => id === categoryId);
if (!hasHiddenAnnounces) {
const dom = new DOMParser().parseFromString(html, 'text/html');
const table = dom.getElementById(form1:Poa00201A:htmlParentTable:${categoryId}:htmlDetailTbl);
return getAnnounceListFromTable(table);
}
// 複数ページあるお知らせリストを全て取得する
let _html = await goDetailedInfoPage(comSunFacesVIEW, categoryId);
let dom = new DOMParser().parseFromString(_html, 'text/html');
const results = [];
while (true) {
const table = dom.getElementById('form1:Poa00201A:htmlParentTable:0:htmlDetailTbl2');
results.push(...getAnnounceListFromTable(table));
// 次ページがなければおしまい
const hasNextPage = !dom.getElementById(nextButtonId).disabled;
if (!hasNextPage) break;
_html = await goNext(dom.getElementById('com.sun.faces.VIEW').value);
dom = new DOMParser().parseFromString(_html, 'text/html');
}
return results;
}
test code
code:js
(async () => {
const {getAnnounceList} = await import('/api/code/takker/CLASSAPI%2Flist/script.js');
console.log(await getAnnounceList(0, {userId: '', password: ''}));
})();
テーブルからお知らせを取得する
code:script.js
function getAnnounceListFromTable(table) {
return ...table.getElementsByClassName('rowHeight')
.flatMap(tr => {
const data = parseAnnounce(tr);
return data ? data : [];
});
}
code:script.d.ts
type Announce = {
unread: boolean;
important: boolean;
title: string;
updated: Date;
page: {
title: string;
sender: string;
lines: string[];
files: string[];
};
};
export function getAnnnounceList(
loginData: {
id: string;
hasHiddenAnnounces: boolean;
announces: Announce[];
},
comSunFacesVIEW: string,
option: {onlyTitle?: boolean},
): Promise<{
announces: Announce[];
}>;
個別のお知らせのDOMを解析する
code:announce.js
export function parseAnnounce(rowHeight) {
const titleDOM = rowHeight.getElementsByClassName('title')0;
const title = titleDOM.firstElementChild.textContent.trim();
if (!title) return undefined;
const unread = rowHeight.firstElementChild.firstElementChild.matches('img');
const important = rowHeight.children1.firstElementChild.matches('img');
const year, month, date = titleDOM.getElementsByClassName('insDate')0.textContent.trim()
.slice(1, -1)
.split('/')
.map(n => parseInt(n));
const updated = new Date(year, month - 1, date);
const id = titleDOM.getElementsByTagName('a')0.id;
return {unread, important, title, updated, id};
}
code:script.js
function createURLSearchParams(data) {
const params = new URLSearchParams();
Object.keys(data).forEach(key => params.append(key, datakey));
return params;
}
#2021-04-05 20:21:27
#2021-03-27 07:23:57
#2021-03-06 16:15:11
#2021-03-05 11:22:30
#2021-02-24 10:56:20