import { IConnection } from "./IConnection" ; import { Appservice , Space } from "matrix-bot-sdk" ; import LogWrapper from "../LogWrapper" ; import axios from "axios" ; import { GitHubDiscussionSpace } from "." ; import { GithubInstance } from "../Github/GithubInstance" ; import { BaseConnection } from "./BaseConnection" ; const log = new LogWrapper ( "GitHubOwnerSpace" ) ; export interface GitHubUserSpaceConnectionState { username : string ; nodeId : string ; } /**
 * Handles rooms connected to a github repo.
 */ export class GitHubUserSpace extends BaseConnection implements IConnection { static readonly CanonicalEventType = "uk.half-shot.matrix-hookshot.github.user.space" ; static readonly LegacyCanonicalEventType = "uk.half-shot.matrix-github.user.space" ; static readonly EventTypes = [ GitHubUserSpace . CanonicalEventType , ] ; static readonly QueryRoomRegex = /#github_(.+):.*/ ; static async onQueryRoom ( result , opts ) { if ( ! result || result . length < 1 ) { log . error ( `Invalid alias pattern '${ result }'` ) ; throw Error ( "Could not find issue" ) ; } const [ username ] = result . slice ( 1 ) ; log . info ( `Fetching ${ username }` ) ; let state ; let avatarUrl ; let name ; const octokit = opts . githubInstance . getOctokitForRepo ( username ) ; try { const userRes = ( await octokit . users . getByUsername ( { username , } ) ) . data ; if ( ! userRes ) { throw Error ( 'User does not exist!' ) ; } name = userRes . name as string ; state = { nodeId : userRes . node_id as string , username : userRes . login as string , } ; avatarUrl = userRes . avatar_url as string ; } catch ( ex ) { log . error ( "Failed to get repo:" , ex ) ; throw Error ( "Could not find repo" ) ; } let avatarState ; try { if ( avatarUrl ) { const res = await axios . get ( avatarUrl , { responseType : 'arraybuffer' , } ) ; log . info ( `uploading ${ avatarUrl }` ) ; const contentType = res . headers [ "content-type" ] ; const mxcUrl = await opts . as . botClient . uploadContent ( Buffer . from ( res . data as ArrayBuffer ) , contentType , `avatar_${ state . username }.png` ) ; avatarState = { type : "m.room.avatar" , state_key : "" , content : { url : mxcUrl , } , } ; } } catch ( ex ) { log . warn ( "Failed to get avatar for org:" , ex ) ; } return { visibility : "public" , name : `GitHub - ${ name } (${ state . username . toLowerCase ( ) })` , topic : `GitHub page of ${ state . username . toLowerCase ( ) }` , preset : 'public_chat' , room_alias_name : `github_${ state . username . toLowerCase ( ) }` , initial_state : [ { type : this . CanonicalEventType , content : state , state_key : state . username . toLowerCase ( ) , } , avatarState , { type : "m.room.history_visibility" , state_key : "" , content : { history_visibility : 'world_readable' , } , } , ] , creation_content : { type : "m.space" , } , power_level_content_override : { ban : 100 , events_default : 50 , invite : 50 , kick : 100 , notifications : { room : 100 , } , redact : 100 , state_default : 100 , users_default : 0 , } , } ; } constructor ( public readonly space , private state , stateKey ) { super ( space . roomId , stateKey , GitHubUserSpace . CanonicalEventType ) ; } public isInterestedInStateEvent ( eventType , stateKey ) { return GitHubUserSpace . EventTypes . includes ( eventType ) && this . stateKey === stateKey ; } public get owner ( ) { return this . state . username . toLowerCase ( ) ; } public toString ( ) { return `GitHubUserSpace ${ this . owner }` ; } public async onRepoConnectionCreated ( discussion ) { log . info ( `Adding connection to ${ this . toString ( ) }` ) ; await this . space . addChildRoom ( discussion . roomId ) ; } public async ensureDiscussionInSpace ( discussion ) { const children = await this . space . getChildEntities ( ) ; if ( ! children [ discussion . roomId ] ) { await this . space . addChildRoom ( discussion . roomId ) ; } } }