member.rb 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. require './app/commands/base_command.rb'
  2. class MemberCommand < BaseCommand
  3. def self.opts
  4. {
  5. # Nav consists of reaction sections and descriptions
  6. nav: {
  7. all: [Emoji::EYES, 'View all info about the character'],
  8. image: [Emoji::PICTURE, "Scroll though the character's images"],
  9. bags: [Emoji::BAGS, "View the character's inventory"],
  10. family: [Emoji::FAMILY, 'View related characters'],
  11. user: [Emoji::BUST, "View the writer's other characters in a list"]
  12. },
  13. # Usage has each option, in order with instructions, and a real example
  14. usage: {
  15. name:
  16. 'Searches characters for the specified name, or discord user. ' +
  17. 'If no name is given, R0ry will show a list of all characters',
  18. section:
  19. 'Skips to the specified section, some options include: bio, type, status, ' +
  20. 'rumors, image, bags. If no section is given, R0ry will default to history',
  21. keyword:
  22. 'Displays a specific image, searched by its title, or keyword. ' +
  23. 'Can only be used if the section option is `image`'
  24. }
  25. }
  26. end
  27. def self.cmd
  28. desc = 'Display info about the guild members'
  29. @cmd ||= Command.new(:member, desc, opts) do |event, name, section, keyword|
  30. # Determine display type: user, character, or list
  31. case name
  32. # Show user's character list
  33. when UID
  34. # Find User to display, and a list of their characters
  35. member = event.server.member(UID.match(name)[1])
  36. characters = Character.where(user_id: UID.match(name)[1])
  37. active_chars = characters.filter { |c| c.active == 'Active' }
  38. # Handle sfw channels and nsfw characters
  39. sfw = !event.channel.nsfw?
  40. sfw_chars = active_chars.filter { |c| c.rating != 'NSFW' }
  41. chars = sfw ? sfw_chars : active_chars
  42. # Generate embed and reply
  43. BotResponse.new(
  44. embed: user_char_embed(characters, member, sfw),
  45. carousel: active_chars.map(&:id),
  46. reactions: Emoji::NUMBERS.take(chars.count).push(Emoji::CROSS)
  47. )
  48. # Show Character List Embed
  49. when nil
  50. # Grab list of active characters, and types
  51. characters = Character.where(active: 'Active').order(:name)
  52. types = Type.all
  53. # Create reaction list
  54. reactions = Emoji::NUMBERS.take(4)
  55. # Generate embed, and reply
  56. BotResponse.new(
  57. embed: char_list_embed(characters, 'active', types),
  58. reactions: reactions.push(Emoji::CROSS),
  59. carousel: 'Guild'
  60. )
  61. # Show character embed
  62. else
  63. # Find Character
  64. if name.to_i > 0
  65. character = Character.find(name)
  66. elsif section&.match(/deleted?/i)
  67. character = Character.where(active: 'Deleted')
  68. .where('name ilike ?', name)
  69. else
  70. character = Character.where.not(active: 'Deleted')
  71. .where('name ilike ?', name)
  72. raise 'Character not found!' if character.empty?
  73. end
  74. char_reply(event, character, section, keyword)
  75. end
  76. rescue ActiveRecord::RecordNotFound => e
  77. error_embed('Record Not Found!', e.message)
  78. # rescue StandardError => e
  79. # error_embed(e.message)
  80. end
  81. end
  82. def self.char_reply(event, character, section, keyword)
  83. # Current channel restricted?
  84. sfw = !event.channel.nsfw?
  85. # Determine if duplicate characters, then filter NSFW if SFW channel
  86. unless character.is_a? Character
  87. chars = sfw ? character.filter { |c| c.rating != 'NSFW' } : character
  88. # If still more than 1 character, reply with duplicate embed
  89. if chars.length > 1
  90. embed = dup_char_embed(chars, chars.first.name)
  91. return BotResponse.new(
  92. embed: embed,
  93. reactions: Emoji::NUMBERS.take(chars.count),
  94. carousel: chars.map(&:id)
  95. )
  96. elsif chars.length == 0
  97. nsfw_char_embed(chars.first, event)
  98. else
  99. character = character.first
  100. end
  101. end
  102. # Find image if specified
  103. image = CharImage.where(char_id: character.id).
  104. find_by('keyword ilike ?', keyword || 'Default')
  105. raise 'Image not found!' if keyword && !image
  106. # Ensure the content is appropriate for the current channel
  107. return nsfw_char_embed(character, event) if sfw && (image&.category == 'NSFW' || character.rating == 'NSFW')
  108. # Generate Character Embed
  109. embed = character_embed(
  110. character: character,
  111. event: event,
  112. section: section,
  113. image: image
  114. )
  115. # Determine Carousel Type and create reply
  116. if section&.match(/images?/i)
  117. BotResponse.new(
  118. embed: embed,
  119. carousel: image,
  120. reactions: ImageCarousel.sections.map { |k, _v| k }.push(Emoji::CROSS)
  121. )
  122. else
  123. BotResponse.new(
  124. embed: embed,
  125. carousel: character,
  126. reactions: CharacterCarousel.sections.map { |k, _v| k }.push(Emoji::CROSS)
  127. )
  128. end
  129. end
  130. def self.example_command(event=nil)
  131. sections = %w[all bio type status rumors image bags]
  132. case ['', 'user', 'name', 'section', 'keyword'].sample
  133. when ''
  134. []
  135. when 'user'
  136. user = Character.where(active: 'Active').order('RANDOM()').first.user_id
  137. member = event&.server&.member(user)
  138. ["@#{member&.nickname || member&.name || 'user_name'}"]
  139. when 'name'
  140. [Character.where.not(active: 'Deleted').order('RANDOM()').first.name]
  141. when 'section'
  142. [Character.where.not(active: 'Deleted').order('RANDOM()').first.name,
  143. sections.sample]
  144. when 'keyword'
  145. i = CharImage.where.not(keyword: 'Default').order('RANDOM()').first
  146. [Character.find(i.char_id).name, 'image', i.keyword]
  147. end
  148. end
  149. end