1 const link
= /(\w+:\/\/(?:[^:/[\]\s
]+|\[[0-9a
-f
:]+\])(?::\d
+)?(?:\/[^/\s
]*)*)/ig
;
2 const XSS
= require('./xss');
4 function sanitizedWithLinksReplaced(text
) {
5 return XSS
.sanitizeText(text
)
6 .replace(link
, '<a href="$1" target="_blank" rel="noopener noreferer">$1</a>');
10 static create(createdBy
, title
, choices
, options
= { hideVotes
: false, retainVotes
: false }) {
11 let poll
= new Poll();
12 poll
.createdAt
= new Date();
13 poll
.createdBy
= createdBy
;
14 poll
.title
= sanitizedWithLinksReplaced(title
);
15 poll
.choices
= choices
.map(choice
=> sanitizedWithLinksReplaced(choice
));
16 poll
.hideVotes
= options
.hideVotes
;
17 poll
.retainVotes
= options
.retainVotes
;
18 poll
.votes
= new Map();
22 static fromChannelData({ initiator
, title
, options
, _counts
, votes
, timestamp
, obscured
, retainVotes
}) {
23 let poll
= new Poll();
24 if (timestamp
=== undefined) // Very old polls still in the database lack timestamps
25 timestamp
= Date
.now();
26 poll
.createdAt
= new Date(timestamp
);
27 poll
.createdBy
= initiator
;
29 poll
.choices
= options
;
30 poll
.votes
= new Map();
31 Object
.keys(votes
).forEach(key
=> {
32 if (votes
[key
] !== null)
33 poll
.votes
.set(key
, votes
[key
]);
35 poll
.hideVotes
= obscured
;
36 poll
.retainVotes
= retainVotes
|| false;
41 let counts
= new Array(this.choices
.length
);
44 // TODO: it would be desirable one day to move away from using an Object here.
45 // This is just for backwards-compatibility with the existing format.
48 this.votes
.forEach((index
, key
) => {
55 initiator
: this.createdBy
,
56 options
: this.choices
,
59 obscured
: this.hideVotes
,
60 retainVotes
: this.retainVotes
,
61 timestamp
: this.createdAt
.getTime()
65 countVote(key
, choiceId
) {
66 if (choiceId
< 0 || choiceId
>= this.choices
.length
)
69 let changed
= !this.votes
.has(key
) || this.votes
.get(key
) !== choiceId
;
70 this.votes
.set(key
, choiceId
);
75 let changed
= this.votes
.has(key
);
76 this.votes
.delete(key
);
80 toUpdateFrame(showHiddenVotes
) {
81 let counts
= new Array(this.choices
.length
);
84 this.votes
.forEach(index
=> counts
[index
]++);
87 counts
= counts
.map(c
=> {
88 if (showHiddenVotes
) return `${c}?`;
95 options
: this.choices
,
97 initiator
: this.createdBy
,
98 timestamp
: this.createdAt
.getTime()