跳到主要内容

Find abandoned rooms by inactivity period

This example demonstrates how to find rooms that have not been updated for a certain number of days in ONLYOFFICE DocSpace. The script retrieves the room list, skips archived rooms, checks the last update date, and prints a simple report of rooms that look abandoned.

Before you start

  1. Replace https://yourportal.onlyoffice.com and YOUR_API_KEY with your actual DocSpace portal URL and API key. Ensure you have the necessary data and permissions to perform these operations.
  2. Before you can make requests to the API, you need to authenticate. Check out the Personal access tokens page to learn how to obtain and use access tokens.
Full example
// Set API base URL
const API_HOST = process.env.DOCSPACE_API_HOST; // Set DOCSPACE_API_HOST in env (recommended). For quick tests you can temporarily paste your portal URL here.
const API_KEY = process.env.DOCSPACE_API_KEY; // Set DOCSPACE_API_KEY in env (recommended). For quick tests you can temporarily paste token here.

const INACTIVITY_DAYS = 10;

const HEADERS = {
Accept: 'application/json',
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
};

async function docspaceRequest(path, method = 'GET', body = null) {
const url = `${API_HOST}${path}`;

try {
const res = await fetch(url, {
method,
headers: HEADERS,
body: body ? JSON.stringify(body) : undefined,
});

if (!res.ok) {
const text = await res.text();
console.log(`Request failed. Status: ${res.status}, Message: ${text}`);
return null;
}

return res.json();
} catch (err: any) {
console.log(`Request error: ${err?.message || err}`);
return null;
}
}

// Step 1: Load rooms list
async function getAllRooms() {
const data = await docspaceRequest('/api/2.0/files/rooms', 'GET');
if (!data) return [];

const raw = data?.response ?? data;

if (Array.isArray(raw)) return raw;

if (raw && typeof raw === 'object') {
if (Array.isArray(raw.rooms)) return raw.rooms;
if (Array.isArray(raw.folders)) return raw.folders;
if (Array.isArray(raw.items)) return raw.items;
}

return [];
}

// Helper: check if room is archived
function isArchivedRoom(room) {
const status = room.roomStatus || room.status;

if (room.isArchived === true) return true;
if (typeof status === 'string' && status.toLowerCase() === 'archived') return true;

return false;
}

// Helper: parse last updated date
function parseRoomLastUpdated(room) {
const candidates = [
room.updated,
room.modified,
room.modifiedOn,
room.lastModified,
room.lastUpdate,
room.updatedOn,
room.created,
room.createdOn,
room.createOn,
];

for (const v of candidates) {
if (!v) continue;

const s = String(v);
const iso = s.endsWith('Z') ? s : s;
const d = new Date(iso);

if (!Number.isNaN(d.getTime())) return d;
}

return null;
}

// Helper: inactivity calculation
function getInactivityInfo(room, now) {
const lastUpdated = parseRoomLastUpdated(room);

if (!lastUpdated) {
return { inactive: true, daysInactive: INACTIVITY_DAYS + 1, lastUpdated: null };
}

const diffMs = now.getTime() - lastUpdated.getTime();
const days = Math.floor(diffMs / (1000 * 60 * 60 * 24));

return { inactive: days >= INACTIVITY_DAYS, daysInactive: days, lastUpdated };
}

// Step 2: Find abandoned rooms
async function findAbandonedRooms() {
const now = new Date();
const rooms = await getAllRooms();

if (!rooms.length) {
console.log('No rooms found.');
return;
}

const abandoned = [];

for (const room of rooms) {
if (!(room.roomType || room.inRoom)) continue;
if (isArchivedRoom(room)) continue;

const info = getInactivityInfo(room, now);
if (!info.inactive) continue;

if (room.id == null) continue;

abandoned.push({
id: Number(room.id),
title: String(room.title || 'Room'),
daysInactive: info.daysInactive,
lastUpdated: info.lastUpdated ? info.lastUpdated.toISOString() : null,
});
}

console.log('--- Abandoned rooms report ---');

if (!abandoned.length) {
console.log(`No rooms found with inactivity >= ${INACTIVITY_DAYS} days.`);
return;
}

abandoned.sort((a, b) => b.daysInactive - a.daysInactive);

for (const r of abandoned) {
let line = `• Room "${r.title}" (ID: ${r.id}) — inactive for ${r.daysInactive} day(s)`;
if (r.lastUpdated) line += `, last updated: ${r.lastUpdated}`;
console.log(line);
}

console.log(`Total abandoned rooms: ${abandoned.length}`);
}

(async () => {
try {
await findAbandonedRooms();
} catch (err: any) {
console.error(err?.message || err);
}
})();

Step 1: Retrieve rooms

A GET request is sent to /api/2.0/files/rooms to retrieve the room list. The response can contain the list in different places (for example, directly in response, or inside folders, items), so the script reads the most common formats.

async function getAllRooms() {
const data = await docspaceRequest('/api/2.0/files/rooms', 'GET');
if (!data) return [];

const raw = data?.response ?? data;

if (Array.isArray(raw)) return raw;

if (raw && typeof raw === 'object') {
if (Array.isArray(raw.rooms)) return raw.rooms;
if (Array.isArray(raw.folders)) return raw.folders;
if (Array.isArray(raw.items)) return raw.items;
}

return [];
}

Step 2: Find abandoned rooms by inactivity

The script goes through the rooms list and builds a report of rooms that look abandoned.

For each room it:

  • Skips archived rooms (for example, isArchived or status values like "archived").
  • Tries to detect the last update date (for example, updated, modifiedOn, updatedOn, etc.).
  • Marks the room as inactive when there were no updates for INACTIVITY_DAYS days (or when the date is missing).
  • Prints a sorted list with room title, room ID, inactive days, and last updated timestamp (if available).
async function findAbandonedRooms() {
const now = new Date();
const rooms = await getAllRooms();

if (!rooms.length) {
console.log('No rooms found.');
return;
}

const abandoned = [];

for (const room of rooms) {
if (!(room.roomType || room.inRoom)) continue;
if (isArchivedRoom(room)) continue;

const info = getInactivityInfo(room, now);
if (!info.inactive) continue;

if (room.id == null) continue;

abandoned.push({
id: Number(room.id),
title: String(room.title || 'Room'),
daysInactive: info.daysInactive,
lastUpdated: info.lastUpdated ? info.lastUpdated.toISOString() : null,
});
}

console.log('--- Abandoned rooms report ---');

if (!abandoned.length) {
console.log(`No rooms found with inactivity >= ${INACTIVITY_DAYS} days.`);
return;
}

abandoned.sort((a, b) => b.daysInactive - a.daysInactive);

for (const r of abandoned) {
let line = `• Room "${r.title}" (ID: ${r.id}) — inactive for ${r.daysInactive} day(s)`;
if (r.lastUpdated) line += `, last updated: ${r.lastUpdated}`;
console.log(line);
}

console.log(`Total abandoned rooms: ${abandoned.length}`);
}