Role management does not work

It seems phantombot is not able to assign roles to discord users. I’ve added some debug output and fixed a seemingly wrong function name in discord/commands/customCommands.js and discord/systems/greetingsSystem.js and JavaScript-wise everything seems to work as expected. Here are the JS changes:
customCommands.js Line 156

        if (s.match(/\(setrole ([\w\W\s]+), ([\w\W\s]+)/)) {
            // custom log instruction
            $.log.file('discrod-role-test', 'Trying to give role "' + s.match(/\(setrole ([\w\W\s]+), ([\w\W\s]+)\)/)[2] + '" to user "' + s.match(/\(setrole ([\w\W\s]+), ([\w\W\s]+)\)/)[1] + '".');
            // this line was `$.discord.addRole(…` before but that function does not exist
            $.discord.setRole(s.match(/\(setrole ([\w\W\s]+), ([\w\W\s]+)\)/)[2], s.match(/\(setrole ([\w\W\s]+), ([\w\W\s]+)\)/)[1]

greetingsSystem.js Line 45:

        if (joinGroup !== '' && joinGroup != null && joinGroup.length > 0) {
            // custom log instruction
            $.log.file('discrod-role-test', 'Greetings system trying to give role "' + joinGroup + '" to user "' + event.getDiscordUser() + '".');
            $.discord.setRole(joinGroup, event.getDiscordUser());
        }

The log output looks like this

[05-20-2020 @ 10:44:25.500 CEST] Trying to give role "Dudes" to user "Robsdedude".
[05-20-2020 @ 10:58:37.342 CEST] Greetings system trying to give role "Dudes" to user "Member{data=MemberData{user=UserData{id=712589983856197695, username=Robsdetester, discriminator=4600, bot=Possible.absent, system=Possible.absent, mfaEnabled=Possible.absent, locale=Possible.absent, verified=Possible.absent, email=Possible.absent, flags=Possible.absent, premiumType=Possible.absent, publicFlags=Possible{0}}, nick=Possible{Optional.empty}, roles=[], joinedAt=2020-05-20T08:58:37.164549+00:00, deaf=false, mute=false}, guildId=711226196355973170} User{data=UserData{id=712589983856197695, username=Robsdetester, discriminator=4600, bot=Possible.absent, system=Possible.absent, mfaEnabled=Possible.absent, locale=Possible.absent, verified=Possible.absent, email=Possible.absent, flags=Possible.absent, premiumType=Possible.absent, publicFlags=Possible{0}}}".

First line is from a custom command (setrole (sender), Dudes)OK! and the second one from the greetings system trying to assign the role “Dudes” to a new user that I created for this test and joined the server with. Both look like I expected, but in both cases the role was not assigned.

So checking out the core-error log reveals this:

[05-20-2020 @ 08:44:25.527 GMT] reactor.core.Exceptions$ErrorCallbackNotImplemented: java.util.NoSuchElementException: Source was empty
Caused by: java.util.NoSuchElementException: Source was empty
	at reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:165)
	at reactor.core.publisher.FluxTake$TakeSubscriber.onComplete(FluxTake.java:146)
	at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:160)
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:78)
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:78)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onComplete(MonoFlatMapMany.java:252)
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:838)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:600)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:580)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onComplete(FluxFlatMap.java:457)
	at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:289)
	at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:225)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:363)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:161)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86)
	at reactor.core.publisher.Flux.subscribe(Flux.java:8325)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:188)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2317)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribe(MonoFlatMapMany.java:134)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4218)
	at reactor.core.publisher.Mono.subscribeWith(Mono.java:4329)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4189)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4125)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4072)
	at tv.phantombot.discord.util.DiscordUtil.lambda$addRole$45(DiscordUtil.java:679)
	at reactor.core.publisher.LambdaMonoSubscriber.onNext(LambdaMonoSubscriber.java:168)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1755)
	at reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:171)
	at reactor.core.publisher.FluxTake$TakeSubscriber.onComplete(FluxTake.java:146)
	at reactor.core.publisher.FluxTake$TakeSubscriber.onNext(FluxTake.java:126)
	at reactor.core.publisher.FluxFilter$FilterSubscriber.onNext(FluxFilter.java:107)
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:242)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:704)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:580)
	at reactor.core.publisher.FluxFlatMap$FlatMapInner.onSubscribe(FluxFlatMap.java:970)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4218)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:418)
	at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:267)
	at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:225)
	at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:363)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:161)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86)
	at reactor.core.publisher.Flux.subscribe(Flux.java:8325)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:188)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2317)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribe(MonoFlatMapMany.java:134)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4218)
	at reactor.core.publisher.Mono.subscribeWith(Mono.java:4329)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4189)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4125)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4072)
	at tv.phantombot.discord.util.DiscordUtil.addRole(DiscordUtil.java:679)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:126)
	at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:225)
	at org.mozilla.javascript.optimizer.OptRuntime.call2(OptRuntime.java:42)
	at org.mozilla.javascript.gen.misc_js_141._c_setRole_11(misc.js:152)
	at org.mozilla.javascript.gen.misc_js_141.call(misc.js)
	at org.mozilla.javascript.optimizer.OptRuntime.call2(OptRuntime.java:42)
	at org.mozilla.javascript.gen.customCommands_js_148._c_tags_3(customCommands.js:161)
	at org.mozilla.javascript.gen.customCommands_js_148.call(customCommands.js)
	at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:63)
	at org.mozilla.javascript.gen.customCommands_js_148._c_anonymous_7(customCommands.js:340)
	at org.mozilla.javascript.gen.customCommands_js_148.call(customCommands.js)
	at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)
	at org.mozilla.javascript.gen.init_js_1._c_callHook_22(init.js:325)
	at org.mozilla.javascript.gen.init_js_1.call(init.js)
	at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:63)
	at org.mozilla.javascript.gen.init_js_1._c_anonymous_29(init.js:595)
	at org.mozilla.javascript.gen.init_js_1.call(init.js)
	at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:393)
	at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3282)
	at org.mozilla.javascript.gen.init_js_1.call(init.js)
	at org.mozilla.javascript.InterfaceAdapter.invokeImpl(InterfaceAdapter.java:137)
	at org.mozilla.javascript.InterfaceAdapter$1.run(InterfaceAdapter.java:83)
	at org.mozilla.javascript.Context.call(Context.java:501)
	at org.mozilla.javascript.ContextFactory.call(ContextFactory.java:503)
	at org.mozilla.javascript.InterfaceAdapter.invoke(InterfaceAdapter.java:86)
	at org.mozilla.javascript.jdk13.VMBridge_jdk13$1.invoke(VMBridge_jdk13.java:132)
	at com.sun.proxy.$Proxy16.handle(Unknown Source)
	at tv.phantombot.script.ScriptEventManager.onEvent(ScriptEventManager.java:75)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at net.engio.mbassy.dispatch.ReflectiveHandlerInvocation.invoke(ReflectiveHandlerInvocation.java:29)
	at net.engio.mbassy.dispatch.MessageDispatcher.dispatch(MessageDispatcher.java:30)
	at net.engio.mbassy.dispatch.FilteredMessageDispatcher.dispatch(FilteredMessageDispatcher.java:42)
	at net.engio.mbassy.subscription.Subscription.publish(Subscription.java:72)
	at net.engio.mbassy.bus.MessagePublication.execute(MessagePublication.java:49)
	at net.engio.mbassy.bus.AbstractSyncAsyncMessageBus$1.run(AbstractSyncAsyncMessageBus.java:67)
	at java.base/java.lang.Thread.run(Thread.java:834)

That error seems to be the reason why the custom command (see timestamp) failed to assign the role. I can’t find any error in the logs, however, that could explain why the greetings system’s attempt to assign the role doesn’t work. I’m also a noob when in comes to Java and didn’t even manage to make the java core build on my system. So making sure that the JavaScript part is working correctly is sadly all I can contribute to this issue. I hope someone can jump in and help me out on this one.

PhantomBot Version:
Java Version: 11.0.6+10-post-Debian-1bpo91
OS Version: Linux 4.14.98-v7+ (arm)
Panel Version: 1.0.2
PhantomBot Version: 3.1.2-NB-20200518 (nightly_build) (Revision: 94003bb)
This most likely also applies to 3.1.2 stable as the java code in question was not changed.

Stock PhantomBot: Yes, except for the above marked changes in the JavaScript

After tracing the error, it appears that it is failing to find you by name in the first test case. The second test case will require a patch

The patch might also fix the first case if there was a difference between your Display Name in the server and your Username

PR #2247

Thank you for fixing it. I’ll test it right away, when the nightly build is ready.

Hey again @gmt2001. I’m afraid the patch fixes neither of the issues. I’m now on Version: 3.1.2-NB-20200525 (nightly_build) (Revision: d069d19) + applying the above stated changes (including $.discord.addRole -> $.discord.setRole by robsdedude · Pull Request #2249 · PhantomBot/PhantomBot · GitHub).

The custom command for the first issue, btw, looks like this (setrole (sender), Dudes)OK! but (setrole (@sender), Dudes)OK! doesn’t work either.

Regarding the second issue: There now is a new error message showing up in the logs:

[05-25-2020 @ 14:07:42.832 GMT] ClientException{request=ClientRequest{method=PUT, url='/guilds/711226196355973170/members/714479769307316245/roles/711248600696487997', headers=DefaultHttpHeaders[], body=null, id=c1312a}, status=403 Forbidden, headers=DefaultHttpHeaders[Date: Mon, 25 May 2020 14:07:42 GMT, Content-Type: application/json, Transfer-Encoding: chunked, Connection: keep-alive, Set-Cookie: __cfduid=ddca05c5a2ad0e070522a84dc16746c2f1590415662; expires=Wed, 24-Jun-20 14:07:42 GMT; path=/; domain=.discordapp.com; HttpOnly; SameSite=Lax, strict-transport-security: max-age=31536000; includeSubDomains, x-ratelimit-bucket: e1e879dfc5003bd7ca461c93344aed2f, x-ratelimit-limit: 10, x-ratelimit-remaining: 9, x-ratelimit-reset: 1590415672.613, x-ratelimit-reset-after: 10.000, x-envoy-upstream-service-time: 19, Via: 1.1 google, CF-Cache-Status: DYNAMIC, Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct", Set-Cookie: __cfruid=8baee0a1067755e346b0c1a640b44ae99523b08b-1590415662; path=/; domain=.discordapp.com; HttpOnly; Secure; SameSite=None, Server: cloudflare, CF-RAY: 598fd302da87d729-FRA, cf-request-id: 02edc235cb0000d729f332a200000001], errorResponse=ErrorResponse{fields={code=50013, message=Missing Permissions}}}
	at discord4j.rest.http.client.ClientResponse.clientException(ClientResponse.java:171)
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ Request to PUT /guilds/711226196355973170/members/714479769307316245/roles/711248600696487997 [RequestStream]
	|_ checkpoint ⇢ Request to PUT /guilds/711226196355973170/members/714479769307316245/roles/711248600696487997 [DefaultRouter]
Stack trace:
		at discord4j.rest.http.client.ClientResponse.clientException(ClientResponse.java:171)
		at discord4j.rest.http.client.ClientResponse.lambda$createException$13(ClientResponse.java:149)
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118)
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1755)
		at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:241)
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1755)
		at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:241)
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1755)
		at reactor.core.publisher.MonoCallable.subscribe(MonoCallable.java:61)
		at reactor.core.publisher.MonoDeferWithContext.subscribe(MonoDeferWithContext.java:54)
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150)
		at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:112)
		at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:845)
		at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:845)
		at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:845)
		at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:213)
		at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:123)
		at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:178)
		at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onNext(FluxContextStart.java:96)
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1755)
		at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:121)
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252)
		at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136)
		at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:366)
		at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:367)
		at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:423)
		at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:607)
		at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:96)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
		at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
		at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
		at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
		at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
		at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1518)
		at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1267)
		at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1314)
		at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501)
		at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:440)
		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
		at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
		at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
		at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
		at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:615)
		at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:578)
		at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
		at java.base/java.lang.Thread.run(Thread.java:834)

Seems my bot doesn’t have the permission to set roles…