-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- List membership (public or "admin_mode") - List applicants (admin_mode only)
- Loading branch information
Showing
14 changed files
with
404 additions
and
21 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { Container } from "typedi"; | ||
import { SpectrumLobby } from "./../src/"; | ||
import { SpectrumChannel } from "./../src/"; | ||
import { SpectrumBroadcaster } from "./../src/"; | ||
import { SpectrumCommunity, SpectrumCommands } from "../src/"; | ||
import { TestInstance } from "./_.instance"; | ||
import { TestShared } from "./_.shared"; | ||
|
||
import {} from "jasmine"; | ||
import { SpectrumCommand } from "../src/Spectrum/components/api/decorators/spectrum-command.decorator"; | ||
|
||
describe("Organizations", () => { | ||
describe(`Management`, () => { | ||
describe(`Member list`, () => { | ||
it(`Should list memberlist`); | ||
it(`Should search through memberlist`); | ||
}) | ||
}) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ | |
*/ /** */ | ||
|
||
export { RSIService as RSI } from "./services/rsi.service"; | ||
export * from "./orgs"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
import { GetApplicants } from "./../interfaces/rsi/get-applicants.interface"; | ||
import { GetApplicantsParams } from "./../interfaces/rsi/get-applicants-params.interface"; | ||
import { | ||
GetOrgMembersOpts, | ||
OrgMemberRank, | ||
OrgMemberVisibility | ||
} from "../interfaces/api/get-org-members-params.interface"; | ||
import { Container } from "typedi"; | ||
import { RSIService } from "../../services/rsi.service"; | ||
import { GetOrgMembers, OrgMember } from "../interfaces/api/get-org-members.interface"; | ||
import { GetOrgMembersOptions } from "../interfaces/api/get-org-members-params.interface"; | ||
import { parse, HTMLElement } from "node-html-parser"; | ||
import { OrgApplicant } from "../interfaces/rsi/get-applicants.interface"; | ||
|
||
/** | ||
* Represents an RSI Organisation | ||
*/ | ||
export class Organisation { | ||
/** main rsi service */ | ||
protected _rsi: RSIService = Container.get(RSIService); | ||
|
||
/** | ||
* @param SSID unique SSID of the organisation | ||
*/ | ||
constructor(public readonly SSID: string) {} | ||
|
||
/** | ||
* Get the list of members for this organisation that can be seen by everyone | ||
* this does not require any specific privilege. | ||
* | ||
* this will **NOT** return "HIDDEN" members and will return no personal info for "REDACTED" members | ||
* | ||
* @param options fetch options | ||
* @see `getMembers()` If you have memberlist privilege and want all the members | ||
*/ | ||
public async getPublicMembers(): Promise<OrgMember[]>; | ||
public async getPublicMembers(options: GetOrgMembersOptions): Promise<OrgMember[]>; | ||
public async getPublicMembers(options?: GetOrgMembersOptions): Promise<OrgMember[]> { | ||
const res = await this._rsi.post<GetOrgMembers>(`api/orgs/getOrgMembers`, { | ||
...options, | ||
symbol: this.SSID | ||
}); | ||
|
||
return this.buildMembersReturn(res.data, options); | ||
} | ||
|
||
/** | ||
* Get the list of members for this organisation. | ||
* You **will** need memberlist privilege for this to work. | ||
* | ||
* @param options fetch options | ||
* @see `getPublicMembers()` for a list of public members if you do not have privilege | ||
*/ | ||
public async getMembers(): Promise<OrgMember[]>; | ||
public async getMembers(options: GetOrgMembersOptions): Promise<OrgMember[]>; | ||
public async getMembers(options?: GetOrgMembersOptions): Promise<OrgMember[]> { | ||
const res = await this._rsi.post<GetOrgMembers>(`api/orgs/getOrgMembers`, { | ||
...options, | ||
admin_mode: 1, | ||
symbol: this.SSID | ||
}); | ||
|
||
return this.buildMembersReturn(res.data, options, true); | ||
} | ||
|
||
/** | ||
* Get the list of current applicants | ||
* | ||
* will fetch the first 500 applicants by default. | ||
*/ | ||
public async getApplicants(): Promise<GetApplicants>; | ||
public async getApplicants(options: GetApplicantsParams): Promise<GetApplicants>; | ||
public async getApplicants( | ||
options: GetApplicantsParams = { page: 1, pagesize: 500 } | ||
): Promise<GetApplicants> { | ||
const res = await this._rsi.navigate( | ||
`orgs/${this.SSID}/admin/applications?page=${options.page}&pagesize=${options.pagesize}` | ||
); | ||
|
||
return this.parseApplicants(res); | ||
} | ||
|
||
/** | ||
* Parse the HTML returned by getApplicants() into an array of OrgApplicant | ||
*/ | ||
protected parseApplicants(resHTML: string): Array<OrgApplicant> { | ||
const root = parse(resHTML); | ||
|
||
|
||
return root | ||
.querySelectorAll("ul.applicants-listing li.clearfix") | ||
.map((li: HTMLElement) => { | ||
const applicant: OrgApplicant = { | ||
id: Number( | ||
(li.querySelectorAll("div.player-cell")[0] as HTMLElement).attributes[ | ||
"data-app-id" | ||
] | ||
), | ||
// no, this is not a typo, they do display the HANDLE in a .nick | ||
handle: li.querySelectorAll("span.nick")[0].text, | ||
nick: li.querySelectorAll("a.name")[0].text, | ||
message: li.querySelectorAll("span.message")[0].text | ||
}; | ||
|
||
return applicant; | ||
}); | ||
} | ||
|
||
protected async buildMembersReturn( | ||
res: GetOrgMembers, | ||
opts?: GetOrgMembersOptions, | ||
admin = false | ||
) { | ||
const firstPassMembers = this.parseMembers(res); | ||
|
||
if (opts && (opts as GetOrgMembersOpts).allMembers) { | ||
if (firstPassMembers.length < res.totalrows) { | ||
/** | ||
* We have to make multiple calls because rsi api | ||
* does not support a pagesize != 32 ... | ||
*/ | ||
for (let i = 2; i <= Math.ceil(res.totalrows / 32); i++) { | ||
// We need to fetch again :( | ||
const res2 = await this._rsi.post<GetOrgMembers>(`api/orgs/getOrgMembers`, { | ||
...opts, | ||
page: i, | ||
admin_mode: admin ? 1 : undefined, | ||
symbol: this.SSID | ||
}); | ||
firstPassMembers.push(...this.parseMembers(res2.data)); | ||
} | ||
} | ||
} | ||
|
||
return firstPassMembers; | ||
} | ||
|
||
/** | ||
* Parse the HTML of a getOrgMembers calls into an OrgMember array | ||
* @param res the res of getOrgMembers call | ||
*/ | ||
protected parseMembers(res: GetOrgMembers) { | ||
const root = parse(res.html); | ||
|
||
const members = root.querySelectorAll("li").map(li => { | ||
const el = li as HTMLElement; | ||
|
||
const user: OrgMember = { | ||
id: Number(el.attributes["data-member-id"]), | ||
handle: el.attributes["data-member-nickname"], | ||
monicker: el.attributes["data-member-displayname"], | ||
avatar: | ||
el.attributes["data-member-avatar"].length > 5 | ||
? el.attributes["data-member-avatar"] | ||
: null, | ||
rank: null, | ||
visibility: null | ||
}; | ||
|
||
const [_, rank] = (el.querySelector("span.ranking-stars") as HTMLElement).classNames | ||
.join(" ") | ||
.match(/data([0-9])/); | ||
|
||
user["rank"] = OrgMemberRank[rank]; | ||
|
||
const [_1, visibility] = (el.querySelector( | ||
"span.visibility" | ||
) as HTMLElement).text.match(/Membership: (.*)/); | ||
|
||
user["visibility"] = visibility.substr(0, 1).toUpperCase() as OrgMemberVisibility; | ||
|
||
return user; | ||
}); | ||
|
||
return members; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Container } from "typedi"; | ||
export { OrgsService } from "./services/orgs.service"; | ||
import { OrgsService } from "./services/orgs.service"; | ||
|
||
const organisations = Container.get(OrgsService); | ||
|
||
export { organisations }; |
79 changes: 79 additions & 0 deletions
79
src/RSI/orgs/interfaces/api/get-org-members-params.interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { Omit } from "../../../interfaces/omit.type"; | ||
|
||
/** | ||
* Params for GetOrgMembers | ||
*/ | ||
export interface GetOrgMembersParams { | ||
/** if we want to do the search as an "admin" (ie: with privilege and see HIDDEN) */ | ||
admin_mode?: 1; | ||
/** filter by member ranks (1 being the higest, 6 the lowest) */ | ||
rank?: OrgMemberRank; | ||
/** filter by member rank () */ | ||
role?: OrgMemberRole; | ||
/** filter by member main/affiliate status (1 = Main only | 0 = Affiliate only) */ | ||
main_org?: 0 | 1; | ||
/** filter by member monicker/handle */ | ||
search?: string; | ||
/** filter by member visibility */ | ||
visibility?: OrgMemberVisibility; | ||
/** SSID of the org to search for */ | ||
symbol: string; | ||
} | ||
|
||
export interface PaginatedGetOrgMembersParam extends GetOrgMembersParams { | ||
page: number; | ||
pagesize: number; | ||
} | ||
|
||
export type GetOrgMembersPaginatedOpts = Omit<PaginatedGetOrgMembersParam, "admin_mode" | "symbol">; | ||
export type GetOrgMembersOpts = Omit<GetOrgMembersParams, "admin_mode" | "symbol"> & { | ||
/** | ||
* return every members in the org | ||
* | ||
* **\/!\ due to an RSI's API limitation, this will generate ceil(OrgMembers / 32) API calls.** | ||
* This is therefore a "little" slow. | ||
* | ||
* If you only want the total **count** of members and not their infos, see GetOrgsMembers.totalrows | ||
*/ | ||
allMembers: boolean; | ||
}; | ||
|
||
/** | ||
* Options for | ||
*/ | ||
export type GetOrgMembersOptions = GetOrgMembersOpts | GetOrgMembersPaginatedOpts; | ||
|
||
/** | ||
* Available ranks in an org for members | ||
*/ | ||
export enum OrgMemberRank { | ||
FIVE_STARS = 1, | ||
FOUR_STARS = 2, | ||
THREE_STARS = 3, | ||
TWO_STARS = 4, | ||
ONE_STAR = 5, | ||
ZERO_STAR = 6 | ||
} | ||
|
||
/** | ||
* Available visibilities in an org for members | ||
*/ | ||
export enum OrgMemberVisibility { | ||
VISIBLE = "V", | ||
REDACTED = "R", | ||
HIDDEN = "H" | ||
} | ||
|
||
/** | ||
* Available roles in an org for main members | ||
*/ | ||
export enum OrgMemberRole { | ||
/**can do anything, from recruiting to customization, to simply disbanding the organization*/ | ||
Owner = 1, | ||
/** can send out invites to the org, and accept or deny applicants */ | ||
Recruitment = 2, | ||
/** can manage the org’s members, and their roles/ranks, as well as moderating the Org’s private Chat channel. */ | ||
Officer = 3, | ||
/**can change the org’s public appearance, official texts, history, manifesto and charter. */ | ||
Marketing = 4 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { OrgMemberRank, OrgMemberVisibility } from "./get-org-members-params.interface"; | ||
|
||
/** | ||
* Raw search result when calling getorgmembers | ||
*/ | ||
export interface GetOrgMembers { | ||
/** total amount of items that matched the search */ | ||
totalrows: number; | ||
/** html containing the list of members in the org */ | ||
html: string; | ||
} | ||
|
||
/** | ||
* Parsed return from GetOrgMembers call | ||
*/ | ||
export interface OrgMember { | ||
id: number; | ||
handle: string; | ||
monicker: string; | ||
avatar: string; | ||
rank: OrgMemberRank; | ||
visibility: OrgMemberVisibility; | ||
} |
4 changes: 4 additions & 0 deletions
4
src/RSI/orgs/interfaces/rsi/get-applicants-params.interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export interface GetApplicantsParams { | ||
page: number; | ||
pagesize: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export type GetApplicants = Array<OrgApplicant>; | ||
|
||
export interface OrgApplicant { | ||
id: number; | ||
handle: string; | ||
nick: string; | ||
/** application message filled by the applicant */ | ||
message: string; | ||
} |
Oops, something went wrong.