赞
踩
下面文章讲解获取OAuth2授权整个流程,创建机器人,使用机器人监听工会(工会就是创建的服务器)成员变化等等,对接国外的都是需要VPN的哦,对接的时候记得提前准备。
点击 此页面添加应用,,创建完成以后会生成应用名称,公钥,客户id等等,这些我们可以保存下来。这些应用会自动和我们的工会关联的。
在下面页面创建一个机器人,机器人会会生成自己的token,这个一定要保存好,注意机器人安全。
页面创建我们的OAuth2,重定向URL需要配置前端页面的URL,因为获取用户token需要重定向到前端页面,这个地方我们自定义配置即可,授权我们可以访问用户的一些功能权限。
创建工会(服务器)直接在discord聊天页面创建就好了,这个就不多说了,那么我们如何将我们的机器人拉入到我们的服务器呢?
选择OAuth2,选择bot,勾选机器人的工会权限,然后下面会生成一个链接。
打开链接会出现下图内容,我们将我们的机器人加入到我们自己的服务器即可。
我们通过上面的步骤成功的创建了我们的应用、工会和机器人,下面我们将介绍如何使用OAuth2相关功能以及操作机器人。
<!-- Discord4J 依赖 --> <dependency> <groupId>com.discord4j</groupId> <artifactId>discord4j-core</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>net.dv8tion</groupId> <artifactId>JDA</artifactId> <version>5.0.0-beta.12</version> </dependency>
根据配置的OAuth2页面生成相关的链接,用户点击授权以后回调到前端页面,页面会带有code以及state参数,code我们用来换取token,state授权页面我们传什么参数过去会给我们带回来的一个参数,授权类似与下面的地址。
拿到token以后我们可以查询用户的信息,用户工会情况等等。
- package com.odcchina.server.api;
-
- import com.odcchina.common.config.BaseComponent;
- import com.odcchina.server.dto.DiscordDto;
- import com.odcchina.server.service.DiscordService;
- import com.odcchina.server.service.GuildEvent;
- import io.swagger.annotations.Api;
- import io.swagger.annotations.ApiOperation;
- import lombok.extern.slf4j.Slf4j;
- import net.dv8tion.jda.api.JDABuilder;
- import net.dv8tion.jda.api.requests.GatewayIntent;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.transaction.annotation.Isolation;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import java.util.HashMap;
- import java.util.Map;
-
- @Slf4j
- @RestController
- @RequestMapping("/discord")
- @Api(tags = "discord服务")
- @Transactional(isolation = Isolation.READ_COMMITTED)
- public class DiscordController extends BaseComponent {
-
- @Autowired
- private DiscordService discordService;
-
- /**
- * 授权回调code
- * @param code
- * @return
- */
- @GetMapping("getDiscordByCode")
- @ApiOperation("获取discord的Code")
- public Map<String, String> getTuiteCode(String code) {
- Map<String, String> map = new HashMap<>();
- //根据code换取token
- DiscordDto discordDto = discordService.getToken(code,null);
- map.put("code", code);
- map.put("access_token", discordDto.getAccessToken());
- map.put("refresh_token", discordDto.getRefreshToken());
- return map;
- }
-
- @GetMapping("findLaborUnionList")
- @ApiOperation("查询我的工会列表")
- public Map<String, String> findLaborUnionList(String token) {
- Map<String, String> map = new HashMap<>();
- try {
- discordService.findLaborUnionList(token);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return map;
- }
-
- @GetMapping("findUserLaborUnion")
- @ApiOperation("查询用户是否存在工会里面")
- public Map<String, String> findUserLaborUnion(String token,String guildId) {
- Map<String, String> map = new HashMap<>();
- try {
- discordService.findUserLaborUnion(token,guildId);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return map;
- }
-
- @GetMapping("findUser")
- @ApiOperation("查询用户信息")
- public Map<String, String> findUser(String token) {
- Map<String, String> map = new HashMap<>();
- try {
- discordService.findUser(token);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return map;
- }
-
- }
-
- package com.odcchina.server.service;
-
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.github.scribejava.apis.DiscordApi;
- import com.odcchina.server.config.DiscordConfig;
- import com.odcchina.server.dto.DiscordDto;
- import com.odcchina.server.dto.DiscordlaborUnionDto;
- import com.odcchina.server.dto.UserDto;
- import lombok.extern.slf4j.Slf4j;
- import net.dv8tion.jda.api.JDA;
- import net.dv8tion.jda.api.JDABuilder;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.http.HttpEntity;
- import org.apache.http.client.ClientProtocolException;
- import org.apache.http.client.entity.UrlEncodedFormEntity;
- import org.apache.http.client.methods.CloseableHttpResponse;
- import org.apache.http.client.methods.HttpGet;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.impl.client.CloseableHttpClient;
- import org.apache.http.impl.client.HttpClientBuilder;
- import org.apache.http.impl.client.HttpClients;
- import org.apache.http.message.BasicNameValuePair;
- import org.apache.http.util.EntityUtils;
- import org.springframework.stereotype.Service;
-
- import java.io.*;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.*;
-
- @Slf4j
- @Service
- public class DiscordService {
-
- /**
- * form表单提交
- * @param url
- * @param map
- * @return
- */
- public DiscordDto doPostForm(String url, Map<String, Object> map) {
- String strResult = "";
- CloseableHttpClient client = HttpClients.createDefault();
- HttpPost httpPost = new HttpPost(url);
- httpPost.setHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
- List<BasicNameValuePair> paramPairs = new ArrayList<>();
- Set<String> keySet = map.keySet();
- for (String key : keySet) {
- Object val = map.get(key);
- paramPairs.add(new BasicNameValuePair(key, val.toString()));
- }
- UrlEncodedFormEntity entity;
- try {
- // 4. 将参数设置到entity对象中
- entity = new UrlEncodedFormEntity(paramPairs, "UTF-8");
- // 5. 将entity对象设置到httppost对象中
- httpPost.setEntity(entity);
- // 6. 发送请求并回去响应
- CloseableHttpResponse resp = client.execute(httpPost);
- try {
- HttpEntity respEntity = resp.getEntity();
- strResult = EntityUtils.toString(respEntity, "UTF-8");
- JSONObject json = JSON.parseObject(strResult.toString());
- Object access_token = json.get("access_token");
- Object refresh_token = json.get("refresh_token");
- Object token_type = json.get("token_type");
- Object expires_in = json.get("expires_in");
- if(access_token == null || refresh_token == null){
- return null;
- }
- DiscordDto discordDto = new DiscordDto();
- discordDto.setAccessToken(access_token.toString());
- discordDto.setRefreshToken(refresh_token.toString());
- discordDto.setTokenType(token_type.toString());
- discordDto.setExpiresIn(Integer.parseInt(expires_in.toString()));
- return discordDto;
- } finally {
- resp.close();
- }
- } catch (ClientProtocolException e) {
- e.printStackTrace();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- // 10. 关闭连接,释放资源
- try {
- client.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-
- /**
- * 根据code换取token
- *
- * @param code
- * @return
- */
- public DiscordDto getToken(String code,String refreshToken) {
- try {
- Map<String, Object> formData = new HashMap<>();
- if(!StringUtils.isBlank(code)){
- formData.put("grant_type", "authorization_code");
- formData.put("code", code);
- }
- if(!StringUtils.isBlank(refreshToken)){
- formData.put("refresh_token", refreshToken);
- formData.put("grant_type", "refresh_token");
- }
- //TODO 重定向配置的URL,一定要和重定向里面的地址保持一致
- formData.put("redirect_uri", 重定向配置的地址URL");
- formData.put("client_id", DiscordConfig.CLIENT_ID);
- formData.put("client_secret", DiscordConfig.CLIENT_SECRET);
- // 创建URL对象
- DiscordDto discordDto = this.doPostForm("https://discord.com/api/oauth2/token",formData);
- return discordDto;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * 获取用户的所有服务器
- * @param token
- * @return
- */
- public List<DiscordlaborUnionDto> findLaborUnionList(String token) {
- try {
- // 设置请求URL和Bearer Token
- CloseableHttpClient httpClient = HttpClientBuilder.create().build();
- HttpGet httpPost = new HttpGet("https://discord.com/api/v9/users/@me/guilds");
- httpPost.setHeader("Content-Type", "application/json;charset=utf8");
- httpPost.setHeader("Authorization", "Bearer " + token);
- CloseableHttpResponse response = null;
- // 由客户端执行(发送)Post请求
- response = httpClient.execute(httpPost);
- // 从响应模型中获取响应实体
- HttpEntity responseEntity = response.getEntity();
- if (response.getStatusLine().getStatusCode() == 200 && responseEntity != null) {
- String responseJson = EntityUtils.toString(responseEntity);
- JSONArray jsonArray = JSON.parseArray(responseJson);
- List<DiscordlaborUnionDto> jsonArrayToStringList = JSONObject.parseArray(jsonArray.toJSONString(),DiscordlaborUnionDto.class);
- return jsonArrayToStringList;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public Boolean findUserLaborUnion(String token, String guildId) {
- try {
- // 设置请求URL和Bearer Token
- CloseableHttpClient httpClient = HttpClientBuilder.create().build();
- HttpGet httpPost = new HttpGet("https://discord.com/api/v9/users/@me/guilds/" + guildId+"/member");
- httpPost.setHeader("Content-Type", "application/json;charset=utf8");
- httpPost.setHeader("Authorization", "Bearer " + token);
- CloseableHttpResponse response = null;
- // 由客户端执行(发送)Post请求
- response = httpClient.execute(httpPost);
- // 从响应模型中获取响应实体
- HttpEntity responseEntity = response.getEntity();
- if (response.getStatusLine().getStatusCode() == 200 && responseEntity != null) {
- String responseJson = EntityUtils.toString(responseEntity);
- JSONObject jsonArray = JSON.parseObject(responseJson);
- if(jsonArray.get("user") != null){
- return true;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
- }
-
- /**
- * 查询用户信息
- * @param token
- * @return
- */
- public UserDto findUser(String token) {
- try {
- // 设置请求URL和Bearer Token
- CloseableHttpClient httpClient = HttpClientBuilder.create().build();
- HttpGet httpPost = new HttpGet("https://discord.com/api/v9/users/@me");
- httpPost.setHeader("Content-Type", "application/json;charset=utf8");
- httpPost.setHeader("Authorization", "Bearer " + token);
- CloseableHttpResponse response = null;
- // 由客户端执行(发送)Post请求
- response = httpClient.execute(httpPost);
- // 从响应模型中获取响应实体
- HttpEntity responseEntity = response.getEntity();
- if (response.getStatusLine().getStatusCode() == 200 && responseEntity != null) {
- String responseJson = EntityUtils.toString(responseEntity);
- JSONObject jsonArray = JSON.parseObject(responseJson);
- UserDto userDto = JSON.toJavaObject(jsonArray, UserDto.class);
- return userDto;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- }
- package com.odcchina.server.dto;
-
- import lombok.Data;
- import lombok.experimental.Accessors;
-
- @Data
- @Accessors(chain = true)
- public class DiscordDto {
-
- /**
- * 访问令牌
- */
- private String accessToken;
-
- /**
- * 刷新令牌
- */
- private String refreshToken;
-
- /**
- * 认证方式 Bearer
- */
- private String tokenType;
-
- /**
- * 过期时间 (秒)
- */
- private Integer expiresIn;
-
- }
- package com.odcchina.server.dto;
-
- import lombok.Data;
- import lombok.experimental.Accessors;
-
- /**
- * 获取工会列表
- */
- @Data
- @Accessors(chain = true)
- public class DiscordlaborUnionDto {
-
-
- /**
- * 工会ID
- */
- public String id;
-
-
- /**
- * 工会名称
- */
- public String name;
-
- }
- package com.odcchina.server.dto;
-
- import lombok.Data;
- import lombok.experimental.Accessors;
-
- @Data
- @Accessors(chain = true)
- public class DiscordUserDto {
-
- /**
- * 服务器ID
- */
- private String guildId;
-
- /**
- * 服务器名称
- */
- private String guildName;
-
- /**
- * 用户ID
- */
- private String userId;
-
- /**
- * 用户名称
- */
- private String userName;
-
- }
- package com.odcchina.server.config;
-
- /**
- * Discord相关配置
- */
- public class DiscordConfig {
-
- /**
- * 客户id和客户私钥
- */
- public static final String CLIENT_ID = "111111";
- public static final String CLIENT_SECRET = "nL8gLAmZEFZYtQQ2mqE3tEYWC111111";
- public static final String PUBLIC_CLIENT_SECRET = "feca6db06a1af3c5ebff8fb3710213b86651f6401623d103a5111111";
-
- public static final String TOKEN_ENDPOINT = "https://discord.com/api/oauth2/token";
- }
工会会员新加入,退出等情况监听,前期我们需要开启下面这些功能,不然机器人无法监听:
- @GetMapping("botMonitor")
- @ApiOperation("开启机器人监听服务")
- public Map<String, String> botMonitor() {
- //启动机器人,监听成员事件
- try {
- //这里是机器人的token的,注意下
- String botToken = "1111.Gh00hD.1111";
- JDABuilder builder = JDABuilder.createDefault(botToken);
- //添加事件监听器
- builder.addEventListeners(new GuildEvent());
- //builder.useSharding(int shardId, int shardTotal)
- //工会成员 GUILD_MEMBERS TODO 这个地方在机器人里面有个选项需要开启,不然无法调用
- builder.enableIntents(GatewayIntent.GUILD_MEMBERS);
- builder.build();
- } catch (Exception e) {
- e.printStackTrace();
- }
当我们启动以后我们的机器人就会在线,由于我没有启动监听,所以我们的机器人在离线中的:
- package com.odcchina.server.service;
-
- import com.odcchina.server.dto.DiscordUserDto;
- import net.dv8tion.jda.api.entities.Guild;
- import net.dv8tion.jda.api.entities.User;
- import net.dv8tion.jda.api.events.guild.GuildLeaveEvent;
- import net.dv8tion.jda.api.events.guild.invite.GuildInviteCreateEvent;
- import net.dv8tion.jda.api.events.guild.invite.GuildInviteDeleteEvent;
- import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
- import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;
- import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent;
- import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent;
- import net.dv8tion.jda.api.hooks.ListenerAdapter;
- import javax.annotation.Nonnull;
-
- public class GuildEvent extends ListenerAdapter {
-
- @Override
- public void onGuildInviteCreate(@Nonnull GuildInviteCreateEvent event) {
- //一个邀请被创建了
- }
-
- @Override
- public void onGuildInviteDelete(@Nonnull GuildInviteDeleteEvent event) {
- //一个邀请被删除了
- }
-
- @Override
- public void onGuildMemberJoin(@Nonnull GuildMemberJoinEvent event) {
- //有新成员进入公会
- Guild guild = event.getGuild();
- User user = event.getUser();
- DiscordUserDto discordUserDto = new DiscordUserDto();
- discordUserDto.setGuildId(guild.getId());
- discordUserDto.setGuildName(guild.getName());
- discordUserDto.setUserId(user.getId());
- discordUserDto.setUserName(user.getName());
- }
-
- @Override
- public void onGuildLeave(@Nonnull GuildLeaveEvent event) {
- //有老成员离开公会
- }
-
- @Override
- public void onGuildMemberRemove(@Nonnull GuildMemberRemoveEvent event) {
- //有成员被移除公会
- }
-
- @Override
- public void onGuildMemberRoleAdd(@Nonnull GuildMemberRoleAddEvent event) {
- //公会成员添加角色
- }
-
- @Override
- public void onGuildMemberRoleRemove(@Nonnull GuildMemberRoleRemoveEvent event) {
- //公会成员移除角色
- }
- }
机器人其他功能调用,比如查询邀请信息,查询邀请我的频道会员
https://discord.com/api/v9/channels/工会ID/invites
关于其他机器人功能实现可以参考下面的文档,大佬写的很详细,点这里
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。