<commit_before>import createDebug from 'debug'
import { flatten, partial } from '../util'

const debug = createDebug('miniplug:users')

const GUEST_ID = 0

export default function usersPlugin () {
  const currentGuestsCount = Symbol('Guests count')
  const currentUsers = Symbol('Users')
  const currentUser = Symbol('Me')

  return (mp) => {
    // local user cache/collection API
    mp[currentGuestsCount] = 0
    mp[currentUsers] = []

    function onUserJoin (user) {
      debug('join', user.id)
      if (user.guest) {
        mp[currentGuestsCount] += 1
        mp.emit('guestJoin')
      } else {
        user = mp.wrapUser(user)
        mp[currentUsers].push(user)
        mp.emit('userJoin', user)
      }
    }

    function onUserLeave (id) {
      debug('leave', id)
      if (id === GUEST_ID) {
        if (mp[currentGuestsCount] > 0) {
          mp[currentGuestsCount] -= 1
        }
        mp.emit('guestLeave')
      } else {
        const i = mp[currentUsers].findIndex((user) => user.id === id)
        if (i !== -1) {
          const user = mp[currentUsers][i]
          mp[currentUsers].splice(i, 1)
          mp.emit('userLeave', user)
        }
      }
    }

    function onUserUpdate (props) {
      const user = mp.user(props.i)
      if (!user) return

      delete props.i
      const oldProps = Object.keys(props).reduce((o, name) => {
        o[name] = user[name]
        return o
      }, {})

      Object.assign(user, props)

      mp.emit('userUpdate', user, oldProps)
    }

    mp.on('connected', (user) => {
      mp[currentUser] = mp.wrapUser(user)

      mp.ws.on('userJoin', onUserJoin)
      mp.ws.on('userLeave', onUserLeave)
      mp.ws.on('userUpdate', onUserUpdate)
    })

    // keeping things in sync
    mp.on('roomState', ({ users, meta: { guests } }) => {
      mp[currentUsers] = users.map(mp.wrapUser)
      mp[currentGuestsCount] = guests
    })

    const me = () => mp[currentUser]
    const user = (id) => mp[currentUsers].find((user) => user.id === id)
    const users = () => mp[currentUsers]
    const guests = () => mp[currentGuestsCount]

    // REST API
    const getMe = () => mp.get('users/me').get(0).then(mp.wrapUser)
    const getUser = uid => mp.get(`users/${uid}`).get(0).then(mp.wrapUser)
    // pass IDs or arrays of IDs<commit_msg>Emit `userUpdate` events for `role` updates.<commit_after>import createDebug from 'debug'
import { flatten, partial } from '../util'

const debug = createDebug('miniplug:users')

const GUEST_ID = 0

export default function usersPlugin () {
  const currentGuestsCount = Symbol('Guests count')
  const currentUsers = Symbol('Users')
  const currentUser = Symbol('Me')

  return (mp) => {
    // local user cache/collection API
    mp[currentGuestsCount] = 0
    mp[currentUsers] = []

    function onUserJoin (user) {
      debug('join', user.id)
      if (user.guest) {
        mp[currentGuestsCount] += 1
        mp.emit('guestJoin')
      } else {
        user = mp.wrapUser(user)
        mp[currentUsers].push(user)
        mp.emit('userJoin', user)
      }
    }

    function onUserLeave (id) {
      debug('leave', id)
      if (id === GUEST_ID) {
        if (mp[currentGuestsCount] > 0) {
          mp[currentGuestsCount] -= 1
        }
        mp.emit('guestLeave')
      } else {
        const i = mp[currentUsers].findIndex((user) => user.id === id)
        if (i !== -1) {
          const user = mp[currentUsers][i]
          mp[currentUsers].splice(i, 1)
          mp.emit('userLeave', user)
        }
      }
    }

    function onUserUpdate (props) {
      const user = mp.user(props.i)
      if (!user) return

      delete props.i
      const oldProps = Object.keys(props).reduce((o, name) => {
        o[name] = user[name]
        return o
      }, {})

      Object.assign(user, props)

      mp.emit('userUpdate', user, oldProps)
    }

    // Emit `userUpdate` events for `role` updates.
    function onStaffUpdate (props) {
      props.u.forEach(({ i, p }) => {
        onUserUpdate({ i, role: p })
      })
    }

    mp.on('connected', (user) => {
      mp[currentUser] = mp.wrapUser(user)

      mp.ws.on('userJoin', onUserJoin)
      mp.ws.on('userLeave', onUserLeave)
      mp.ws.on('userUpdate', onUserUpdate)
      mp.ws.on('modStaff', onStaffUpdate)
    })

    // keeping things in sync
    mp.on('roomState', ({ users, meta: { guests } }) => {
      mp[currentUsers] = users.map(mp.wrapUser)
      mp[currentGuestsCount] = guests
    })

    const me = () => mp[currentUser]
    const user = (id) => mp[currentUsers].find((user) => user.id === id)
    const users = () => mp[currentUsers]
    const guests = () => mp[currentGuestsCount]

    // REST API
    const getMe = () => mp.get('users/me').get(0).then(mp.wrapUser)
    const getUser = uid => mp.get(`users/${uid}`).get(0).then(mp.wrapUser)
    // pass IDs or arrays of IDs
{'fraction_non_alphanumeric': 0.1578622816032888, 'fraction_numerical': 0.0036998972250770813, 'mean_word_length': 2.386221294363257, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5539633', 'n_tokens_mistral': 1621, 'n_tokens_neox': 1585, 'n_words': 342}