member.rb 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. # Generate embed and reply
  39. BotResponse.new(
  40. embed: user_char_embed(characters, member),
  41. carousel: active_chars.map(&:id),
  42. reactions: Emoji::NUMBERS.take(active_chars.count).push(Emoji::CROSS)
  43. )
  44. # Show Character List Embed
  45. when nil
  46. # Grab list of active characters, and types
  47. characters = Character.where(active: 'Active').order(:name)
  48. types = Type.all
  49. # Create reaction list
  50. reactions = Emoji::NUMBERS.take(4)
  51. # Generate embed, and reply
  52. BotResponse.new(
  53. embed: char_list_embed(characters, 'active', types),
  54. reactions: reactions.push(Emoji::CROSS)
  55. )
  56. # Show character embed
  57. when Integer
  58. # Find Character by ID and generate embed
  59. character = Character.find(name)
  60. char_reply(event, character, section, keyword)
  61. else
  62. # Find Character by name and generate embed
  63. character = Character.where('name ilike ?', name)
  64. raise 'Character not found!' if character.empty?
  65. char_reply(event, character, section, keyword)
  66. end
  67. rescue ActiveRecord::RecordNotFound => e
  68. error_embed("Record Not Found!", e.message)
  69. rescue StandardError => e
  70. error_embed(e.message)
  71. end
  72. end
  73. def self.char_reply(event, character, section, keyword)
  74. # Current channel restricted?
  75. sfw = !event.channel.nsfw?
  76. # Determine if duplicate characters, then filter NSFW if SFW channel
  77. if character.count > 1 && sfw
  78. chars = character.filter{ |c| c.rating == 'SFW' || c.rating == 'Hidden' } if sfw
  79. # If still more than 1 character, reply with duplicate embed
  80. if chars.length > 1
  81. embed = dup_char_embed(chars, chars.first.name)
  82. return BotResponse.new(
  83. embed: embed,
  84. reactions: Emoji::NUMBERS.take(chars.count)
  85. )
  86. end
  87. end
  88. character = character.first
  89. # Find image if specified
  90. image = CharImage.where(char_id: character.id).
  91. find_by(keyword: keyword || 'Default')
  92. # Ensure the content is appropriate for the current channel
  93. if sfw && ( image&.category == 'NSFW' || character.rating == 'NSFW' )
  94. return nsfw_char_embed(character, event)
  95. end
  96. # Generate Character Embed
  97. embed = character_embed(
  98. character: character,
  99. event: event,
  100. section: section,
  101. image: image
  102. )
  103. # Determine Carousel Type and create reply
  104. if section&.match(/images?/i)
  105. BotResponse.new(
  106. embed: embed,
  107. carousel: image,
  108. reactions: ImageCarousel.sections.map{ |k,v| k }.push(Emoji::CROSS)
  109. )
  110. else
  111. BotResponse.new(
  112. embed: embed,
  113. carousel: character,
  114. reactions: CharacterCarousel.sections.map{ |k,v| k }.push(Emoji::CROSS)
  115. )
  116. end
  117. end
  118. def self.example_command(event=nil)
  119. sections = ['all', 'bio', 'type', 'status', 'rumors', 'image', 'bags']
  120. case ['', 'user', 'name', 'section', 'keyword'].sample
  121. when ''
  122. []
  123. when 'user'
  124. user = Character.where(active: 'Active').order('RANDOM()').first.user_id
  125. member = event&.server&.member(user)
  126. ["@#{member&.nickname || member&.name || 'user_name'}"]
  127. when 'name'
  128. [Character.where.not(active: 'Deleted').order('RANDOM()').first.name]
  129. when 'section'
  130. [Character.where.not(active: 'Deleted').order('RANDOM()').first.name,
  131. sections.sample]
  132. when 'keyword'
  133. i = CharImage.where.not(keyword: 'Default').order('RANDOM()').first
  134. [Character.find(i.char_id).name, 'image', i.keyword]
  135. end
  136. end
  137. end