Class: Elephrame::Bots::GenerativeBot

Inherits:
BaseBot
  • Object
show all
Includes:
Command, Reply, Scheduler, Streaming
Defined in:
lib/elephrame/mix/generative.rb

Direct Known Subclasses

EbooksBot, MarkovBot

Constant Summary collapse

SavedFileName =
'model.yml'
SavedFilterFileName =
'filter.yml'

Constants inherited from BaseBot

BaseBot::FNGabLink, BaseBot::NoBotRegex

Instance Attribute Summary collapse

Attributes included from Command

#cmd_hash, #cmd_regex, #commands, #not_found, #prefix

Attributes included from Reply

#on_reply

Attributes included from Scheduler

#schedule, #scheduler

Attributes included from Streaming

#streamer

Attributes inherited from BaseBot

#client, #failed, #max_retries, #strip_html, #username

Instance Method Summary collapse

Methods included from Command

#add_command, #if_not_found, #run_commands, #set_help, #set_prefix, #setup_command

Methods included from Reply

#reply, #reply_with_mentions, #run_reply

Methods included from Scheduler

#run_scheduled, #setup_scheduler

Methods included from Streaming

#setup_streaming

Methods inherited from BaseBot

backup_method, #fetch_account_id, #fetch_list_id, #find_ancestor, #no_bot?

Constructor Details

#initialize(interval, options = {}) ⇒ GenerativeBot

Returns a new instance of GenerativeBot.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/elephrame/mix/generative.rb', line 26

def initialize(interval, options = {})
  require 'moo_ebooks'
  require 'yaml'
  
  # initialize our botness
  super()
  
  # setup our various classes
  setup_streaming
  setup_scheduler interval
  setup_command
  
  # set some defaults and initialize some vars
  @model_hash = { model: Ebooks::Model.new,
                  last_id:  {} }
  @filter = /^$/
  @filter_words = []
  @following = []
  @char_limit = @client.instance.max_toot_chars || 500
  @retry_limit = options[:retry_limit] || 10
  @cw = options[:cw] || 'markov post'
  @visibility = options[:visibility] || 'unlisted'
  @model_filename = options[:model_filename] || SavedFileName
  @filter_filename = options[:filter_filename] || SavedFilterFileName
  
  # load our model if it exists
  if File.exists? @model_filename
    values = load_file(@model_filename)
    @model_hash[:model] = Ebooks::Model.from_hash(values.first)
    @model_hash[:last_id] = values.last
  end
  
  @filter_words = load_file(@filter_filename) if File.exists? @filter_filename
  
  # add our default commands
  #
  # !delete will delete the status it's in reply to
  add_privileged_command 'delete' do |bot, content, status|
    @client.destroy_status(status.in_reply_to_id)
  end
  
  # !filter will add every word from the post into the word filter
  add_privileged_command 'filter' do |bot, content, status|
    content.split.each do |word|
      add_filter_word word
    end
    save_file @filter_filename, @filter_words.to_yaml
    bot.reply("'#{content}' added to internal filter")
  end

  # add a help command that explains the other commands
  add_privileged_command 'help' do |bot|
    bot.reply(default_help)
  end
  
  # set up a default for replying
  on_reply do |bot, status|
    # retry our status creation until we get something that
    #  passes our filters
    @retry_limit.times do
      text = @model_hash[:model].reply(status
                                         .content
                                         .gsub(/@.+?(@.+?)?\s/, ''),
                                       @char_limit)
      break unless bot.reply_with_mentions(text,
                                           spoiler: @cw).nil?
    end
  end
  
  # get our own account id and save the ids of the accounts
  #  we're following
  acct_id = @client.verify_credentials.id
  @client.following(acct_id).each do ||
    @following << .id
  end
end

Instance Attribute Details

#char_limitObject (readonly)

Returns the value of attribute char_limit.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def char_limit
  @char_limit
end

#cwObject

Returns the value of attribute cw.



9
10
11
# File 'lib/elephrame/mix/generative.rb', line 9

def cw
  @cw
end

#filterObject

Returns the value of attribute filter.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def filter
  @filter
end

#filter_by(&block) ⇒ Object (readonly)

Accepts a block to check the post against before posting

Parameters:

  • block (Proc)


212
213
214
# File 'lib/elephrame/mix/generative.rb', line 212

def filter_by
  @filter_by
end

#filter_filenameObject (readonly)

Returns the value of attribute filter_filename.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def filter_filename
  @filter_filename
end

#filter_wordsObject (readonly)

Returns a string representing all of the current

words being checked in the filter


193
194
195
# File 'lib/elephrame/mix/generative.rb', line 193

def filter_words
  @filter_words
end

#followingObject (readonly)

Returns the value of attribute following.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def following
  @following
end

#modelObject (readonly)

Returns the value of attribute model.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def model
  @model
end

#model_filenameObject (readonly)

Returns the value of attribute model_filename.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def model_filename
  @model_filename
end

#model_hashObject (readonly)

Returns the value of attribute model_hash.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def model_hash
  @model_hash
end

#retry_limitObject (readonly)

Returns the value of attribute retry_limit.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def retry_limit
  @retry_limit
end

#visibilityObject (readonly)

Returns the value of attribute visibility.



10
11
12
# File 'lib/elephrame/mix/generative.rb', line 10

def visibility
  @visibility
end

Instance Method Details

#add_filter_word(word) ⇒ Object

Adds a word into the filter list

Parameters:

  • word (String)


202
203
204
205
# File 'lib/elephrame/mix/generative.rb', line 202

def add_filter_word(word)
  @filter_words << word
  filter = @filter_words
end

#add_privileged_command(cmd, &block) ⇒ Object

adds a command that can only be executed by someone

that the bot follows

Parameters:

  • cmd (String)

    a command to add

  • block (Proc)

    the code to execute when cmd is recieved



148
149
150
151
152
153
154
# File 'lib/elephrame/mix/generative.rb', line 148

def add_privileged_command cmd, &block
  add_command cmd do |bot, content, status|
    if @following.include? status..id
      block.call(bot, content, status)
    end
  end
end

#default_helpObject

generates a default help message for the default commands if you add custom commands add a ‘custom_command_help` method that returns a string. it will be added to the end of this



132
133
134
135
136
137
138
139
# File 'lib/elephrame/mix/generative.rb', line 132

def default_help
  txt = []
  txt << "#{@prefix}delete -- deletes the status that the command post is replying to"
  txt << "#{@prefix}filter -- adds all words from the command post into the internal filter"
  txt << "#{@prefix}help -- replies with this help text"
  txt << custom_command_help if respond_to? :custom_command_help
  txt.join "\n"
end

#filter_and_post(text, *options) ⇒ Object Also known as: post

Checks the proposed post against the filters

only posts if the text passes the filters

Parameters:

  • text (String)

    the tracery text to expand before posting

  • options (Hash)

    a hash of arguments to pass to post

Options Hash (*options):

  • rules (String)

    the grammar rules to load

  • visibility (String)

    visibility level

  • spoiler (String)

    text to use as content warning

  • reply_id (String)

    id of post to reply to

  • hide_media (Bool)

    should we hide media?

  • media (Array<String>)

    array of file paths



229
230
231
232
233
234
235
236
237
238
239
# File 'lib/elephrame/mix/generative.rb', line 229

def filter_and_post(text, *options)
  opts = Hash[*options]
  
  # default passed to false and then see if
  #  the supplied text gets through our filters
  passed = false
  passed = !(text =~ @filter)
  passed = @filter_by.call(text) unless @filter_by.nil?
  
  actually_post(text, **opts) if passed
end

#load_file(filename) ⇒ Object

loads a yaml file containing our model data

Parameters:

  • filename (String)

    file to read in from



161
162
163
# File 'lib/elephrame/mix/generative.rb', line 161

def load_file filename
  YAML.load_file(filename)
end

#runObject

Runs the bot



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/elephrame/mix/generative.rb', line 106

def run
  # see scheduler.rb
  run_scheduled do |bot|
    @retry_limit.times do
      text = @model_hash[:model].update(@char_limit)
      break unless bot.post(text,
                            spoiler: @cw,
                            visibility: @visibility).nil?
    end
  end
  
  # we do this because run_commands accepts a block that
  #  will run when it doesn't find a command in a mention
  #  this should work. :shrug:
  run_commands do |bot, status|
    @on_reply.call(bot, status)
  end
end

#save_file(filename, data) ⇒ Object

Saves a yaml file containing our model data

Parameters:

  • filename (String)

    file to write out to



170
171
172
# File 'lib/elephrame/mix/generative.rb', line 170

def save_file filename, data
  File.write(filename, data)
end