mirror of
https://github.com/kissyjpf/rtm-sync.git
synced 2026-07-22 07:02:51 +00:00
fix: resolve RTM API task addition parsing and signature validation errors
This commit is contained in:
parent
dd3ed3f216
commit
6ca1380b95
2 changed files with 66 additions and 29 deletions
32
main.js
32
main.js
File diff suppressed because one or more lines are too long
63
src/main.ts
63
src/main.ts
|
|
@ -31,6 +31,7 @@ interface RtmResponse {
|
|||
stat: string;
|
||||
err?: { msg: string };
|
||||
lists?: { list: RtmList | RtmList[] };
|
||||
list?: RtmTaskList | RtmTaskList[];
|
||||
tasks?: { list: RtmTaskList | RtmTaskList[] };
|
||||
timeline?: string;
|
||||
frob?: string;
|
||||
|
|
@ -371,13 +372,40 @@ export default class RtmPlugin extends Plugin {
|
|||
const timeline = await this.getTimeline();
|
||||
const res = await this.callRtmApi('rtm.tasks.add', { timeline: timeline, name: taskName, parse: '1' });
|
||||
|
||||
const rawList = res.rsp.tasks?.list;
|
||||
const rawList = res.rsp.list;
|
||||
if (!rawList) {
|
||||
console.error("API Response does not contain 'list':", res);
|
||||
throw new Error("API Response missing 'list'. Check console for details.");
|
||||
}
|
||||
const list: RtmTaskList = (Array.isArray(rawList) ? rawList[0] : rawList) as RtmTaskList;
|
||||
if (!list.id) {
|
||||
console.error("API Response list missing 'id':", res);
|
||||
throw new Error("API Response list missing 'id'. Check console for details.");
|
||||
}
|
||||
const listId = list.id;
|
||||
|
||||
const seriesRaw = list.taskseries;
|
||||
if (!seriesRaw) {
|
||||
console.error("API Response does not contain 'taskseries':", res);
|
||||
throw new Error("API Response missing 'taskseries'. Check console for details.");
|
||||
}
|
||||
const series: RtmTaskSeries = (Array.isArray(seriesRaw) ? seriesRaw[0] : seriesRaw) as RtmTaskSeries;
|
||||
if (!series.id) {
|
||||
console.error("API Response series missing 'id':", res);
|
||||
throw new Error("API Response series missing 'id'. Check console for details.");
|
||||
}
|
||||
const taskSeriesId = series.id;
|
||||
const taskObj: RtmTask = (Array.isArray(series.task) ? series.task[0] : series.task) as RtmTask;
|
||||
|
||||
const taskRaw = series.task;
|
||||
if (!taskRaw) {
|
||||
console.error("API Response does not contain 'task':", res);
|
||||
throw new Error("API Response missing 'task'. Check console for details.");
|
||||
}
|
||||
const taskObj: RtmTask = (Array.isArray(taskRaw) ? taskRaw[0] : taskRaw) as RtmTask;
|
||||
if (!taskObj.id) {
|
||||
console.error("API Response taskObj missing 'id':", res);
|
||||
throw new Error("API Response taskObj missing 'id'. Check console for details.");
|
||||
}
|
||||
const taskId = taskObj.id;
|
||||
|
||||
// 現在の設定に従ってデフォルト期日を設定
|
||||
|
|
@ -458,17 +486,20 @@ export default class RtmPlugin extends Plugin {
|
|||
}
|
||||
|
||||
async callRtmApi(method: string, params: Record<string, string> = {}): Promise<RtmResponse> {
|
||||
const apiKey = this.settings.apiKey;
|
||||
const sharedSecret = this.settings.sharedSecret;
|
||||
const apiKey = this.settings.apiKey?.trim();
|
||||
const sharedSecret = this.settings.sharedSecret?.trim();
|
||||
if(!apiKey || !sharedSecret) throw new Error("API Key/Secret missing");
|
||||
|
||||
const apiParams: Record<string, string> = { ...params, method, api_key: apiKey, format: 'json', auth_token: this.settings.authToken };
|
||||
const apiParams: Record<string, string> = { ...params, method, api_key: apiKey, format: 'json', auth_token: this.settings.authToken?.trim() ?? "" };
|
||||
const keys = Object.keys(apiParams).sort();
|
||||
let sigString = sharedSecret;
|
||||
for (const key of keys) sigString += key + apiParams[key];
|
||||
apiParams['api_sig'] = md5(sigString);
|
||||
|
||||
const url = `${RTM_REST_URL}?${new URLSearchParams(apiParams).toString()}`;
|
||||
const queryString = Object.keys(apiParams)
|
||||
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(apiParams[k] ?? "")}`)
|
||||
.join('&');
|
||||
const url = `${RTM_REST_URL}?${queryString}`;
|
||||
const res = await requestUrl({ url: url });
|
||||
const json = res.json as RtmResponse;
|
||||
if(json.rsp.stat !== 'ok') {
|
||||
|
|
@ -651,14 +682,17 @@ class RtmSettingTab extends PluginSettingTab {
|
|||
}
|
||||
async startAuthProcess() {
|
||||
const rtm = this.plugin;
|
||||
const apiKey = rtm.settings.apiKey;
|
||||
const sharedSecret = rtm.settings.sharedSecret;
|
||||
const apiKey = rtm.settings.apiKey?.trim();
|
||||
const sharedSecret = rtm.settings.sharedSecret?.trim();
|
||||
if (!apiKey || !sharedSecret) { new Notice('Enter keys first'); return; }
|
||||
const frobParams: Record<string, string> = { method: 'rtm.auth.getFrob', api_key: apiKey, format: 'json' };
|
||||
let sigString = sharedSecret;
|
||||
Object.keys(frobParams).sort().forEach(k => sigString += k + frobParams[k]);
|
||||
frobParams['api_sig'] = md5(sigString);
|
||||
const frobRes = await requestUrl({ url: `${RTM_REST_URL}?${new URLSearchParams(frobParams).toString()}` });
|
||||
const frobQueryString = Object.keys(frobParams)
|
||||
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(frobParams[k] ?? "")}`)
|
||||
.join('&');
|
||||
const frobRes = await requestUrl({ url: `${RTM_REST_URL}?${frobQueryString}` });
|
||||
const frob = (frobRes.json as RtmResponse).rsp.frob ?? '';
|
||||
const authParams: Record<string, string> = { api_key: apiKey, perms: 'delete', frob };
|
||||
let authSigString = sharedSecret;
|
||||
|
|
@ -675,14 +709,17 @@ class TokenModal extends Modal {
|
|||
onOpen() {
|
||||
const {contentEl} = this;
|
||||
new Setting(contentEl).addButton(btn => btn.setButtonText('Finish Auth').setCta().onClick(async () => {
|
||||
const apiKey = this.plugin.settings.apiKey;
|
||||
const sharedSecret = this.plugin.settings.sharedSecret;
|
||||
const tokenParams: Record<string, string> = { method: 'rtm.auth.getToken', api_key: apiKey, format: 'json', frob: this.frob };
|
||||
const apiKey = this.plugin.settings.apiKey?.trim();
|
||||
const sharedSecret = this.plugin.settings.sharedSecret?.trim();
|
||||
const tokenParams: Record<string, string> = { method: 'rtm.auth.getToken', api_key: apiKey ?? "", format: 'json', frob: this.frob };
|
||||
let sig = sharedSecret;
|
||||
Object.keys(tokenParams).sort().forEach(k => sig += k + tokenParams[k]);
|
||||
tokenParams['api_sig'] = md5(sig);
|
||||
try {
|
||||
const res = await requestUrl({ url: `${RTM_REST_URL}?${new URLSearchParams(tokenParams).toString()}` });
|
||||
const tokenQueryString = Object.keys(tokenParams)
|
||||
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(tokenParams[k] ?? "")}`)
|
||||
.join('&');
|
||||
const res = await requestUrl({ url: `${RTM_REST_URL}?${tokenQueryString}` });
|
||||
const json = res.json as RtmResponse;
|
||||
if(json.rsp.auth) {
|
||||
this.plugin.settings.authToken = json.rsp.auth.token;
|
||||
|
|
|
|||
Loading…
Reference in a new issue