github.com/Jeffail/benthos/v3@v3.65.0/template/inputs/discord.yaml (about) 1 name: discord 2 type: input 3 status: experimental 4 categories: [ Services, Social ] 5 summary: Consumes messages posted in a Discord channel. 6 description: This input works by polling the `/channels/{channel_id}/messages` Discord API endpoint authenticated as a bot using token based authentication. The ID of the newest message consumed is stored in a cache in order to paginate results, ideally this cache should be persisted across restarts in order for the service to resume where it left off. 7 8 fields: 9 - name: channel_id 10 description: A discord channel ID to consume messages from. 11 type: string 12 13 - name: bot_token 14 description: A bot token used for authentication. 15 type: string 16 17 - name: poll_period 18 description: The length of time (as a duration string) to wait between each poll for new messages. This field can be set empty, in which case requests are made at the limit set by the rate limit. This field also supports cron expressions. 19 type: string 20 default: "1m" 21 22 - name: limit 23 description: The maximum number of messages to receive in a single request. 24 type: int 25 default: 100 26 27 - name: cache 28 description: A cache resource to use for request pagination, the ID of the last message received will be stored in this cache and used for subsequent requests. 29 type: string 30 31 - name: cache_key 32 description: The key identifier used when storing the ID of the last message received. 33 type: string 34 default: last_message_id 35 advanced: true 36 37 - name: rate_limit 38 description: An optional rate limit resource to restrict API requests with. 39 type: string 40 default: "" 41 advanced: true 42 43 mapping: | 44 let _ = if this.poll_period == "" && this.rate_limit == "" { 45 throw("either a poll_period, a rate_limit, or both must be specified") 46 } 47 48 let url_mapping = """meta discord_messages_url = "https://discord.com/api/channels/%v/messages?limit=%v" + if content().length() > 0 { 49 "&after="+content().string() 50 } else { "" } 51 root = "" 52 """.format(this.channel_id, this.limit) 53 54 root.generate.interval = this.poll_period 55 root.generate.mapping = "root = \"\"" 56 57 root.processors = [] 58 59 root.processors."-".cache = { 60 "resource": this.cache, 61 "operator": "get", 62 "key": this.cache_key, 63 } 64 65 root.processors."-".catch = [] # Don't care if the cache is empty 66 67 root.processors."-".bloblang = $url_mapping 68 69 root.processors."-".http = { 70 "url": """${! meta("discord_messages_url") }""", 71 "verb": "GET", 72 "rate_limit": this.rate_limit, 73 "headers": { 74 "Authorization": "Bot " + this.bot_token, 75 }, 76 } 77 78 root.processors."-".bloblang = "root = if (this | []).length() == 0 { deleted() } else { this.sort_by(ele -> ele.timestamp.format_timestamp_unix()) }" 79 80 root.processors."-".unarchive = { 81 "format": "json_array", 82 } 83 84 root.processors."-".cache = { 85 "parts": [ -1 ], 86 "resource": this.cache, 87 "operator": "set", 88 "key": this.cache_key, 89 "value": """${! json("id") }""", 90 } 91 92 root.processors."-".catch = [ 93 { 94 "log": { 95 "level": "ERROR", 96 "message": "Failed to write latest message ID to cache: ${! error() }", 97 } 98 } 99 ] 100 101 root.processors."-".split = {} 102 103 metrics_mapping: | 104 root = match this { 105 this.has_suffix("processor.7.count") => this.replace("processor.7.count", "count"), 106 this.has_suffix("processor.3.client.error") => this.replace("processor.3.client.error", "error"), 107 this.contains("processor.3.client.error") => deleted(), # Ignore more specialized client errors 108 this.contains("processor.3.client") => this.replace("processor.3.client", "request"), 109 _ => deleted(), 110 } 111 112 tests: 113 - name: Basic fields 114 config: 115 channel_id: 1234 116 limit: 45 117 cache: foocache 118 rate_limit: foolimit 119 bot_token: foobot 120 121 expected: 122 generate: 123 interval: '1m' 124 mapping: root = "" 125 processors: 126 - cache: 127 resource: foocache 128 operator: get 129 key: last_message_id 130 131 - catch: [] 132 133 - bloblang: | 134 meta discord_messages_url = "https://discord.com/api/channels/1234/messages?limit=45" + if content().length() > 0 { 135 "&after="+content().string() 136 } else { "" } 137 root = "" 138 139 - http: 140 url: ${! meta("discord_messages_url") } 141 verb: GET 142 rate_limit: foolimit 143 headers: 144 Authorization: Bot foobot 145 146 - bloblang: root = if (this | []).length() == 0 { deleted() } else { this.sort_by(ele -> ele.timestamp.format_timestamp_unix()) } 147 148 - unarchive: 149 format: json_array 150 151 - cache: 152 # Only bother caching the latest message ID (last of the batch). 153 parts: [ -1 ] 154 resource: foocache 155 operator: set 156 key: last_message_id 157 value: ${! json("id") } 158 159 - catch: 160 - log: 161 level: ERROR 162 message: "Failed to write latest message ID to cache: ${! error() }" 163 164 - split: {}