Skip to content

Commit

Permalink
feat: Add Support for Sent By
Browse files Browse the repository at this point in the history
Allows to specify the calendar user that is acting on behalf of the calendar user. Both supported within the Organizator and Attendees.

see #358
  • Loading branch information
sebbo2002 committed Mar 19, 2022
1 parent 4b59b60 commit 9aac3e0
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 26 deletions.
31 changes: 31 additions & 0 deletions src/attendee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface ICalInternalAttendeeData {
name: string | null;
email: string | null;
mailto: string | null;
sentBy: string | null;
status: ICalAttendeeStatus | null;
role: ICalAttendeeRole;
rsvp: boolean | null;
Expand All @@ -22,6 +23,7 @@ export interface ICalAttendeeData {
name?: string | null;
email?: string | null;
mailto?: string | null;
sentBy?: string | null;
status?: ICalAttendeeStatus | null;
role?: ICalAttendeeRole;
rsvp?: boolean | null;
Expand All @@ -37,6 +39,7 @@ export interface ICalAttendeeJSONData {
name: string | null;
email: string | null;
mailto: string | null;
sentBy: string | null;
status: ICalAttendeeStatus | null;
role: ICalAttendeeRole;
rsvp: boolean | null;
Expand Down Expand Up @@ -105,6 +108,7 @@ export default class ICalAttendee {
name: null,
email: null,
mailto: null,
sentBy: null,
status: null,
role: ICalAttendeeRole.REQ,
rsvp: null,
Expand All @@ -121,6 +125,7 @@ export default class ICalAttendee {
data.name !== undefined && this.name(data.name);
data.email !== undefined && this.email(data.email);
data.mailto !== undefined && this.mailto(data.mailto);
data.sentBy !== undefined && this.sentBy(data.sentBy);
data.status !== undefined && this.status(data.status);
data.role !== undefined && this.role(data.role);
data.rsvp !== undefined && this.rsvp(data.rsvp);
Expand Down Expand Up @@ -195,6 +200,27 @@ export default class ICalAttendee {
}


/**
* Get the acting user's email adress
* @since 3.3.0
*/
sentBy(): string | null;

/**
* Set the acting user's email adress
* @since 3.3.0
*/
sentBy(email: string | null): this;
sentBy(email?: string | null): this | string | null {
if (!email) {
return this.data.sentBy;
}

this.data.sentBy = email;
return this;
}


/**
* Get attendee's role
* @since 0.2.0
Expand Down Expand Up @@ -549,6 +575,11 @@ export default class ICalAttendee {
g += ';RSVP=' + this.data.rsvp.toString().toUpperCase();
}

// SENT-BY
if (this.data.sentBy !== null) {
g += ';SENT-BY="mailto:' + this.data.sentBy + '"';
}

// DELEGATED-TO
if (this.data.delegatedTo) {
g += ';DELEGATED-TO="' + this.data.delegatedTo.email() + '"';
Expand Down
8 changes: 6 additions & 2 deletions src/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -823,13 +823,14 @@ export default class ICalEvent {
* event.organizer('Organizer\'s Name <organizer@example.com>');
* ```
*
* You can also add an explicit `mailto` email address.
* You can also add an explicit `mailto` email address or or the sentBy address.
*
* ```javascript
* event.organizer({
* name: 'Organizer\'s Name',
* email: 'organizer@example.com',
* mailto: 'explicit@mailto.com'
* mailto: 'explicit@mailto.com',
* sentBy: 'substitute@example.com'
* })
* ```
*
Expand Down Expand Up @@ -1585,6 +1586,9 @@ export default class ICalEvent {
if (this.data.organizer) {
g += 'ORGANIZER;CN="' + escape(this.data.organizer.name) + '"';

if (this.data.organizer.sentBy) {
g += ';SENT-BY="mailto:' + escape(this.data.organizer.sentBy) + '"';
}
if (this.data.organizer.email && this.data.organizer.mailto) {
g += ';EMAIL=' + escape(this.data.organizer.email);
}
Expand Down
3 changes: 2 additions & 1 deletion src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ export function checkNameAndMail (attribute: string, value: string | ICalOrganiz
result = {
name: value.name,
email: value.email,
mailto: value.mailto
mailto: value.mailto,
sentBy: value.sentBy
};
}

Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface ICalOrganizer {
name: string;
email?: string;
mailto?: string;
sentBy?: string;
}

export interface ICalDescription {
Expand Down
70 changes: 50 additions & 20 deletions test/attendee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
import assert from 'assert';
import ICalCalendar from '../src/calendar';
import ICalEvent from '../src/event';
import ICalAttendee, {ICalAttendeeData, ICalAttendeeRole, ICalAttendeeStatus, ICalAttendeeType} from '../src/attendee';
import ICalAttendee, {
ICalAttendeeData,
ICalAttendeeRole,
ICalAttendeeStatus,
ICalAttendeeType
} from '../src/attendee';

describe('ical-generator Attendee', function () {
describe('constructor()', function () {
Expand All @@ -12,6 +17,7 @@ describe('ical-generator Attendee', function () {
name: 'John Doe',
email: 'john@example.org',
mailto: 'john+calendar@example.org',
sentBy: null,
status: ICalAttendeeStatus.ACCEPTED,
role: ICalAttendeeRole.REQ,
rsvp: false,
Expand All @@ -27,7 +33,7 @@ describe('ical-generator Attendee', function () {
it('shouldn\'t work without event reference', function () {
assert.throws(function () {
// @ts-ignore
new ICalAttendee({email: 'foo@bar.com'});
new ICalAttendee({ email: 'foo@bar.com' });
}, /`event`/);
});
});
Expand Down Expand Up @@ -70,7 +76,7 @@ describe('ical-generator Attendee', function () {
});

it('should change something', function () {
const a = new ICalAttendee({email: 'mail@example.com'}, new ICalEvent({}, new ICalCalendar()));
const a = new ICalAttendee({ email: 'mail@example.com' }, new ICalEvent({}, new ICalCalendar()));
assert.ok(a.toString().indexOf('mail@example.com') > -1);
});
});
Expand All @@ -91,7 +97,7 @@ describe('ical-generator Attendee', function () {
});

it('should change mailto and keep email if present', function () {
const a = new ICalAttendee({email: 'mail@example.com'}, new ICalEvent({}, new ICalCalendar()));
const a = new ICalAttendee({ email: 'mail@example.com' }, new ICalEvent({}, new ICalCalendar()));
a.mailto('mail2@example2.com');
assert.ok(
a.toString().indexOf('EMAIL=mail@example.com') > -1 &&
Expand All @@ -100,6 +106,23 @@ describe('ical-generator Attendee', function () {
});
});

describe('sentBy()', function () {
it('getter should return value', function () {
const a = new ICalAttendee({}, new ICalEvent({}, new ICalCalendar())).sentBy('foo@example.com');
assert.strictEqual(a.sentBy(), 'foo@example.com');
});

it('setter should return this', function () {
const a = new ICalAttendee({}, new ICalEvent({}, new ICalCalendar()));
assert.deepStrictEqual(a, a.sentBy('foo@example.com'));
});

it('should change something', function () {
const a = new ICalAttendee({ email: 'foo@example.com', sentBy: 'bar@example.com' }, new ICalEvent({}, new ICalCalendar()));
assert.ok(a.toString().includes('bar@example.com'));
});
});

describe('role()', function () {
it('setter should return this', function () {
const a = new ICalAttendee({}, new ICalEvent({}, new ICalCalendar()));
Expand Down Expand Up @@ -136,8 +159,8 @@ describe('ical-generator Attendee', function () {
});
});

describe('rsvp()', function() {
it('setter should return this', function() {
describe('rsvp()', function () {
it('setter should return this', function () {
const a = new ICalAttendee({}, new ICalEvent({}, new ICalCalendar()));
assert.deepStrictEqual(a, a.rsvp(null));
assert.deepStrictEqual(a, a.rsvp(true));
Expand All @@ -153,7 +176,7 @@ describe('ical-generator Attendee', function () {
assert.strictEqual(a.rsvp(), false);
});

it('getter should return value', function() {
it('getter should return value', function () {
const a = new ICalAttendee({}, new ICalEvent({}, new ICalCalendar()));
assert.strictEqual(a.rsvp(), null);
a.rsvp(false);
Expand All @@ -162,8 +185,11 @@ describe('ical-generator Attendee', function () {
assert.strictEqual(a.rsvp(), null);
});

it('should change something', function() {
const a = new ICalAttendee({email: 'mail@example.com', rsvp: true}, new ICalEvent({}, new ICalCalendar()));
it('should change something', function () {
const a = new ICalAttendee({
email: 'mail@example.com',
rsvp: true
}, new ICalEvent({}, new ICalCalendar()));
assert.ok(a.toString().indexOf(';RSVP=TRUE') > -1);
});
});
Expand Down Expand Up @@ -196,15 +222,15 @@ describe('ical-generator Attendee', function () {

it('should change something', function () {
const a = new ICalAttendee(
{email: 'mail@example.com', status: ICalAttendeeStatus.DECLINED},
{ email: 'mail@example.com', status: ICalAttendeeStatus.DECLINED },
new ICalEvent({}, new ICalCalendar())
);
assert.ok(a.toString().indexOf('DECLINED') > -1);
});

it('should change something too', function () {
const a = new ICalAttendee(
{email: 'mail@example.com', status: ICalAttendeeStatus.NEEDSACTION},
{ email: 'mail@example.com', status: ICalAttendeeStatus.NEEDSACTION },
new ICalEvent({}, new ICalCalendar())
);
assert.ok(a.toString().indexOf('NEEDS-ACTION') > -1);
Expand Down Expand Up @@ -294,7 +320,10 @@ describe('ical-generator Attendee', function () {
});

it('should change something', function () {
const a = new ICalAttendee({email: 'mail@example.com', delegatedFrom: 'foo@example.com'}, new ICalEvent({}, new ICalCalendar()));
const a = new ICalAttendee({
email: 'mail@example.com',
delegatedFrom: 'foo@example.com'
}, new ICalEvent({}, new ICalCalendar()));
assert.ok(a.toString().indexOf('foo@example.com') > -1);
});
});
Expand All @@ -307,14 +336,14 @@ describe('ical-generator Attendee', function () {

it('should reuse the same ICalAttendee instance if passed', function () {
const event = new ICalEvent({}, new ICalCalendar());
const attendee = new ICalAttendee({name: 'Muh'}, event);
const attendee = new ICalAttendee({ name: 'Muh' }, event);

assert.deepStrictEqual(new ICalAttendee({}, event).delegatesTo(attendee), attendee);
});

it('should pass data to instance', function () {
const attendee = new ICalAttendee({name: 'Zac'}, new ICalEvent({}, new ICalCalendar()))
.delegatesTo({name: 'Cody'});
const attendee = new ICalAttendee({ name: 'Zac' }, new ICalEvent({}, new ICalCalendar()))
.delegatesTo({ name: 'Cody' });

assert.strictEqual(attendee.name(), 'Cody');
});
Expand All @@ -328,27 +357,27 @@ describe('ical-generator Attendee', function () {

it('should reuse the same ICalAttendee instance if passed', function () {
const event = new ICalEvent({}, new ICalCalendar());
const attendee = new ICalAttendee({name: 'Muh'}, event);
const attendee = new ICalAttendee({ name: 'Muh' }, event);

assert.deepStrictEqual(new ICalAttendee({}, event).delegatesFrom(attendee), attendee);
});

it('should pass data to instance', function () {
const a = new ICalAttendee({name: 'Zac'}, new ICalEvent({}, new ICalCalendar())).delegatesFrom({name: 'Cody'});
const a = new ICalAttendee({ name: 'Zac' }, new ICalEvent({}, new ICalCalendar())).delegatesFrom({ name: 'Cody' });
assert.strictEqual(a.name(), 'Cody');
});
});

describe('x()', function () {
it('works as expected', function () {
const a = new ICalAttendee({email: 'foo@example.org'}, new ICalEvent({}, new ICalCalendar()));
const a = new ICalAttendee({ email: 'foo@example.org' }, new ICalEvent({}, new ICalCalendar()));
assert.deepStrictEqual(a, a.x('X-NUM-GUESTS', '5'));
assert.ok(a.toString().includes('ATTENDEE;ROLE=REQ-PARTICIPANT;X-NUM-GUESTS=5:MAILTO:foo@example.org'));
});
});

describe('toJSON()', function () {
it('should work', function() {
it('should work', function () {
const a = new ICalAttendee({}, new ICalEvent({}, new ICalCalendar()));
a.name('Max Mustermann');
a.delegatesTo('Moritz <moritz@example.com>');
Expand All @@ -358,6 +387,7 @@ describe('ical-generator Attendee', function () {
delegatedTo: 'moritz@example.com',
email: null,
mailto: null,
sentBy: null,
name: 'Max Mustermann',
role: 'REQ-PARTICIPANT',
rsvp: null,
Expand All @@ -375,7 +405,7 @@ describe('ical-generator Attendee', function () {

describe('generate()', function () {
it('should throw an error without email', function () {
const a = new ICalAttendee({name: 'Testuser'}, new ICalEvent({}, new ICalCalendar()));
const a = new ICalAttendee({ name: 'Testuser' }, new ICalEvent({}, new ICalCalendar()));
assert.throws(function () {
a.toString();
}, /`email`/);
Expand Down
24 changes: 21 additions & 3 deletions test/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1209,14 +1209,31 @@ describe('ical-generator Event', function () {
assert.deepStrictEqual(event.organizer(), {
name: 'Sebastian Pekarek',
email: 'mail@example.com',
mailto: undefined
mailto: undefined,
sentBy: undefined
});

event.organizer({name: 'Sebastian Pekarek', email: 'mail@example.com', mailto: 'mail2@example2.com'});
assert.deepStrictEqual(event.organizer(), {
name: 'Sebastian Pekarek',
email: 'mail@example.com',
mailto: 'mail2@example2.com'
mailto: 'mail2@example2.com',
sentBy: undefined
});
});

it('should support sent by when using object', function () {
const event = new ICalEvent({
start: moment(),
summary: 'Example Event'
}, new ICalCalendar());

event.organizer({name: 'Sebastian Pekarek', email: 'mail@example.com', sentBy: 'bot@example.com'});
assert.deepStrictEqual(event.organizer(), {
name: 'Sebastian Pekarek',
email: 'mail@example.com',
mailto: undefined,
sentBy: 'bot@example.com'
});
});

Expand Down Expand Up @@ -1267,7 +1284,8 @@ describe('ical-generator Event', function () {
assert.deepStrictEqual(event.organizer(), {
name: 'Sebastian Pekarek',
email: undefined,
mailto: undefined
mailto: undefined,
sentBy: undefined
});
});
});
Expand Down

0 comments on commit 9aac3e0

Please sign in to comment.