mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-15 10:15:23 +08:00
feat(route)(v2): add 旅法师营地首页 (#8350)
This commit is contained in:
10
docs/game.md
10
docs/game.md
@@ -481,9 +481,17 @@ Steam 新闻中心支持官方的 RSS 订阅:
|
|||||||
|
|
||||||
## 旅法师营地
|
## 旅法师营地
|
||||||
|
|
||||||
|
### 首页
|
||||||
|
|
||||||
|
<Route author="auto-bot-ty" example="/lfsyd/home" path="/lfsyd/home" radar="1" rssbud="1"/>
|
||||||
|
|
||||||
|
### 首页(旧版)
|
||||||
|
|
||||||
|
<Route author="auto-bot-ty" example="/lfsyd/old_home" path="/lfsyd/old_home" radar="1" rssbud="1"/>
|
||||||
|
|
||||||
### 分区
|
### 分区
|
||||||
|
|
||||||
<Route author="auto-bot-ty" example="/lfsyd/tag/17" path="/lfsyd/tag/:tag" :paramsDesc="['订阅分区类型']" radar="1" rssbud="1">
|
<Route author="auto-bot-ty" example="/lfsyd/tag/17" path="/lfsyd/tag/:tagId" :paramsDesc="['订阅分区类型']" radar="1" rssbud="1">
|
||||||
|
|
||||||
| 炉石传说 | 万智牌 | 游戏王 | 昆特牌 | 影之诗 | 符文之地传奇 | 阴阳师百闻牌 |
|
| 炉石传说 | 万智牌 | 游戏王 | 昆特牌 | 影之诗 | 符文之地传奇 | 阴阳师百闻牌 |
|
||||||
| :------: | :----: | :----: | :----: | :----: | :----------: | :----------: |
|
| :------: | :----: | :----: | :----: | :----: | :----------: | :----------: |
|
||||||
|
|||||||
@@ -325,11 +325,6 @@ router.get('/nytimes/:lang?', lazyloadRouteHandler('./routes/nytimes/index'));
|
|||||||
router.get('/3dm/:name/:type', lazyloadRouteHandler('./routes/3dm/game'));
|
router.get('/3dm/:name/:type', lazyloadRouteHandler('./routes/3dm/game'));
|
||||||
router.get('/3dm/news', lazyloadRouteHandler('./routes/3dm/news_center'));
|
router.get('/3dm/news', lazyloadRouteHandler('./routes/3dm/news_center'));
|
||||||
|
|
||||||
// 旅法师营地
|
|
||||||
router.get('/lfsyd/:typecode', lazyloadRouteHandler('./routes/lfsyd/index'));
|
|
||||||
router.get('/lfsyd/user/:id', lazyloadRouteHandler('./routes/lfsyd/user'));
|
|
||||||
router.get('/lfsyd/tag/:tag', lazyloadRouteHandler('./routes/lfsyd/tag'));
|
|
||||||
|
|
||||||
// 喜马拉雅
|
// 喜马拉雅
|
||||||
router.get('/ximalaya/album/:id/:all?', lazyloadRouteHandler('./routes/ximalaya/album'));
|
router.get('/ximalaya/album/:id/:all?', lazyloadRouteHandler('./routes/ximalaya/album'));
|
||||||
router.get('/ximalaya/album/:id/:all/:shownote?', lazyloadRouteHandler('./routes/ximalaya/album'));
|
router.get('/ximalaya/album/:id/:all/:shownote?', lazyloadRouteHandler('./routes/ximalaya/album'));
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
const got = require('@/utils/got');
|
|
||||||
|
|
||||||
module.exports = async (ctx) => {
|
|
||||||
const code_dict = {
|
|
||||||
1: 'home',
|
|
||||||
2: 'heartstone',
|
|
||||||
3: 'mtg',
|
|
||||||
4: 'videogame',
|
|
||||||
17: 'verse',
|
|
||||||
16: 'yugioh',
|
|
||||||
67: 'artifact',
|
|
||||||
62: 'twozerofortyseven',
|
|
||||||
9: 'boardgame',
|
|
||||||
22: 'mobilegame',
|
|
||||||
21: 'yingdi',
|
|
||||||
5: 'yingdistation',
|
|
||||||
68: 'hunwu',
|
|
||||||
14: 'gwent',
|
|
||||||
};
|
|
||||||
const host = 'https://www.iyingdi.com';
|
|
||||||
const game = code_dict[ctx.params.typecode];
|
|
||||||
let url;
|
|
||||||
if (game === 'home') {
|
|
||||||
url = `${host}/feed/list/user/v3?feedIdUp=0&feedIdDown=0&feedSize=30&RSSize=10&hotfeed=1&system=web`;
|
|
||||||
} else {
|
|
||||||
url = `${host}/feed/list/seed/v2?web=1&seed=${ctx.params.typecode}&system=web`;
|
|
||||||
}
|
|
||||||
const response = await got.get(url);
|
|
||||||
const feeds = response.data.feeds;
|
|
||||||
|
|
||||||
const items = feeds
|
|
||||||
.map((element) => {
|
|
||||||
const date = new Date(element.feed.created * 1000);
|
|
||||||
const video = element.feed.clazz === 'video' ? 'clazz=video&' : '';
|
|
||||||
const link = element.feed.clazz === 'bbsPost' ? 'bbspost/detail' : `article/${game}`;
|
|
||||||
return {
|
|
||||||
title: element.feed.title,
|
|
||||||
description: `<img src="${element.feed.icon}" /><br><p>${element.feed.description}</p>`,
|
|
||||||
pubDate: `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`,
|
|
||||||
link: `${host}/web/${link}/${element.feed.sourceID.split('/')[0]}?${video}title=${encodeURI(element.feed.seedTitle)}&remark=seed`,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.filter((item) => item.title !== undefined);
|
|
||||||
|
|
||||||
ctx.state.data = {
|
|
||||||
title: `旅法师营地 - ${ctx.params.typecode === '1' ? '首页资讯' : feeds['0'].feed.seedTitle}`,
|
|
||||||
link: url,
|
|
||||||
item: items,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
42
lib/v2/lfsyd/home.js
Normal file
42
lib/v2/lfsyd/home.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
const got = require('@/utils/got');
|
||||||
|
const { parseDate } = require('@/utils/parse-date');
|
||||||
|
const { ProcessForm, ProcessFeed } = require('./utils');
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const rootUrl = 'https://www.iyingdi.com';
|
||||||
|
const url = 'https://api.iyingdi.com/mweb/feed/recommend-content-list';
|
||||||
|
const form = {
|
||||||
|
size: 30,
|
||||||
|
timestamp: '',
|
||||||
|
};
|
||||||
|
const response = await got({
|
||||||
|
method: 'post',
|
||||||
|
url,
|
||||||
|
headers: {
|
||||||
|
'App-Udid': 'unknown',
|
||||||
|
Host: 'api.iyingdi.com',
|
||||||
|
'Login-Token': 'nologin',
|
||||||
|
Origin: 'https://mob.iyingdi.com',
|
||||||
|
Platform: 'mweb',
|
||||||
|
Preid: '86f2007de00272e24a54831a621aecc5',
|
||||||
|
Referer: 'https://mob.iyingdi.com/',
|
||||||
|
},
|
||||||
|
form: ProcessForm(form, 'mweb'),
|
||||||
|
});
|
||||||
|
const { posts } = response.data;
|
||||||
|
|
||||||
|
const articleList = posts.map((item) => ({
|
||||||
|
title: item.post.title,
|
||||||
|
pubDate: parseDate(item.post.show_time * 1000),
|
||||||
|
link: `${rootUrl}/tz/post/${item.post.id}`,
|
||||||
|
guid: item.post.title,
|
||||||
|
postId: item.post.id,
|
||||||
|
}));
|
||||||
|
const items = await ProcessFeed(ctx.cache, articleList);
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: '首页 - 旅法师营地',
|
||||||
|
link: rootUrl,
|
||||||
|
item: items,
|
||||||
|
};
|
||||||
|
};
|
||||||
7
lib/v2/lfsyd/maintainer.js
Normal file
7
lib/v2/lfsyd/maintainer.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// 旅法师营地
|
||||||
|
module.exports = {
|
||||||
|
'/home': ['auto-bot-ty'],
|
||||||
|
'/old_home': ['auto-bot-ty'],
|
||||||
|
'/user/:id?': ['auto-bot-ty'],
|
||||||
|
'/tag/:tagId?': ['auto-bot-ty'],
|
||||||
|
};
|
||||||
29
lib/v2/lfsyd/old_home.js
Normal file
29
lib/v2/lfsyd/old_home.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const got = require('@/utils/got');
|
||||||
|
const { parseDate } = require('@/utils/parse-date');
|
||||||
|
const { ProcessFeed } = require('./utils');
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const limit = ctx.query.limit ?? 10;
|
||||||
|
const rootUrl = 'https://www.iyingdi.com';
|
||||||
|
const url = `${rootUrl}/feed/list/user/v3?feedIdUp=0&feedIdDown=0&hotfeed=1&system=web`;
|
||||||
|
const { data } = await got(url);
|
||||||
|
|
||||||
|
const articleList = data.feeds
|
||||||
|
.slice(0, limit)
|
||||||
|
.map((element) => ({
|
||||||
|
title: element.feed.title,
|
||||||
|
pubDate: parseDate(element.feed.created * 1000),
|
||||||
|
link: `${rootUrl}/tz/post/${element.feed.sourceID}`,
|
||||||
|
guid: element.feed.title,
|
||||||
|
postId: element.feed.sourceID,
|
||||||
|
}))
|
||||||
|
.filter((item) => item.title !== undefined);
|
||||||
|
|
||||||
|
const items = await ProcessFeed(ctx.cache, articleList);
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: '旅法师营地 - 首页资讯(旧版)',
|
||||||
|
link: rootUrl,
|
||||||
|
item: items,
|
||||||
|
};
|
||||||
|
};
|
||||||
39
lib/v2/lfsyd/radar.js
Normal file
39
lib/v2/lfsyd/radar.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
module.exports = {
|
||||||
|
'iyingdi.com': {
|
||||||
|
_name: '旅法师营地',
|
||||||
|
www: [
|
||||||
|
{
|
||||||
|
title: '分区',
|
||||||
|
docs: 'https://docs.rsshub.app/game.html#lv-fa-shi-ying-di',
|
||||||
|
source: ['/tz/tag/:tagId'],
|
||||||
|
target: '/lfsyd/tag/:tagId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户发帖',
|
||||||
|
docs: 'https://docs.rsshub.app/game.html#lv-fa-shi-ying-di',
|
||||||
|
source: ['/tz/people/:id', '/tz/people/:id/*'],
|
||||||
|
target: '/lfsyd/user/:id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '首页',
|
||||||
|
docs: 'https://docs.rsshub.app/game.html#lv-fa-shi-ying-di',
|
||||||
|
source: ['/'],
|
||||||
|
target: '/lfsyd/home',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '首页(旧版)',
|
||||||
|
docs: 'https://docs.rsshub.app/game.html#lv-fa-shi-ying-di',
|
||||||
|
source: ['/'],
|
||||||
|
target: '/lfsyd/old_home',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mob: [
|
||||||
|
{
|
||||||
|
title: '分区(mob)',
|
||||||
|
docs: 'https://docs.rsshub.app/game.html#lv-fa-shi-ying-di',
|
||||||
|
source: ['/fine/:tagId'],
|
||||||
|
target: '/lfsyd/tag/:tagId',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
6
lib/v2/lfsyd/router.js
Normal file
6
lib/v2/lfsyd/router.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = function (router) {
|
||||||
|
router.get('/home', require('./home'));
|
||||||
|
router.get('/old_home', require('./old_home'));
|
||||||
|
router.get('/user/:id?', require('./user'));
|
||||||
|
router.get('/tag/:tagId?', require('./tag'));
|
||||||
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
const got = require('@/utils/got');
|
const got = require('@/utils/got');
|
||||||
const util = require('./utils');
|
|
||||||
const { parseDate } = require('@/utils/parse-date');
|
const { parseDate } = require('@/utils/parse-date');
|
||||||
|
const { ProcessForm, ProcessFeed } = require('./utils');
|
||||||
|
|
||||||
module.exports = async (ctx) => {
|
module.exports = async (ctx) => {
|
||||||
const tagId = ctx.params.tag;
|
const { tagId } = ctx.params;
|
||||||
const tagList = {
|
const tagList = {
|
||||||
17: '炉石传说',
|
17: '炉石传说',
|
||||||
18: '万智牌',
|
18: '万智牌',
|
||||||
@@ -40,9 +40,10 @@ module.exports = async (ctx) => {
|
|||||||
Platform: 'pc',
|
Platform: 'pc',
|
||||||
Referer: `${rootUrl}/`,
|
Referer: `${rootUrl}/`,
|
||||||
},
|
},
|
||||||
form: util.getForm(form),
|
form: ProcessForm(form),
|
||||||
});
|
});
|
||||||
const list = response.data.list;
|
|
||||||
|
const { list } = response.data;
|
||||||
const tagJson = JSON.parse(list[0].feed.tag_json);
|
const tagJson = JSON.parse(list[0].feed.tag_json);
|
||||||
|
|
||||||
const articleList = list.map((item) => ({
|
const articleList = list.map((item) => ({
|
||||||
@@ -53,12 +54,11 @@ module.exports = async (ctx) => {
|
|||||||
postId: item.feed.source_id,
|
postId: item.feed.source_id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const items = await Promise.all(articleList.map((item) => util.ProcessFeed(ctx, item)));
|
const items = await ProcessFeed(ctx.cache, articleList);
|
||||||
|
|
||||||
ctx.state.data = {
|
ctx.state.data = {
|
||||||
title: `${!tagName ? tagJson[0].tag : tagName} - 旅法师营地 `,
|
title: `${tagName || tagJson[0].tag} - 旅法师营地 `,
|
||||||
link: `${rootUrl}/tz/tag/${tagId}`,
|
link: `${rootUrl}/tz/tag/${tagId}`,
|
||||||
description: `${!tagName ? tagJson[0].tag : tagName} - 旅法师营地 `,
|
|
||||||
item: items,
|
item: items,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
1
lib/v2/lfsyd/templates/card.art
Normal file
1
lib/v2/lfsyd/templates/card.art
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<a href = "{{ url }}"></a>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
const got = require('@/utils/got');
|
const got = require('@/utils/got');
|
||||||
const util = require('./utils');
|
|
||||||
const { parseDate } = require('@/utils/parse-date');
|
const { parseDate } = require('@/utils/parse-date');
|
||||||
|
const { ProcessForm, ProcessFeed } = require('./utils');
|
||||||
|
|
||||||
module.exports = async (ctx) => {
|
module.exports = async (ctx) => {
|
||||||
const id = ctx.params.id;
|
const id = ctx.params.id;
|
||||||
@@ -24,12 +24,13 @@ module.exports = async (ctx) => {
|
|||||||
Platform: 'pc',
|
Platform: 'pc',
|
||||||
Referer: `${rootUrl}/tz/people/${id}/postList`,
|
Referer: `${rootUrl}/tz/people/${id}/postList`,
|
||||||
},
|
},
|
||||||
form: util.getForm(form),
|
form: ProcessForm(form),
|
||||||
});
|
});
|
||||||
const list = response.data.data;
|
|
||||||
const nickname = list[0].author.nickname;
|
|
||||||
|
|
||||||
const articleList = list.map((item) => ({
|
const { data } = response.data;
|
||||||
|
const { nickname } = data[0].author;
|
||||||
|
|
||||||
|
const articleList = data.map((item) => ({
|
||||||
title: item.event_data.title,
|
title: item.event_data.title,
|
||||||
pubDate: parseDate(item.event_data.show_time * 1000),
|
pubDate: parseDate(item.event_data.show_time * 1000),
|
||||||
link: `${rootUrl}/tz/post/${item.event_data.post_id}`,
|
link: `${rootUrl}/tz/post/${item.event_data.post_id}`,
|
||||||
@@ -37,12 +38,11 @@ module.exports = async (ctx) => {
|
|||||||
postId: item.event_data.post_id,
|
postId: item.event_data.post_id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const items = await Promise.all(articleList.map((item) => util.ProcessFeed(ctx, item)));
|
const items = await ProcessFeed(ctx.cache, articleList);
|
||||||
|
|
||||||
ctx.state.data = {
|
ctx.state.data = {
|
||||||
title: `${nickname} - 旅法师营地 `,
|
title: `${nickname} - 旅法师营地 `,
|
||||||
link: `${rootUrl}/tz/people/${id}`,
|
link: `${rootUrl}/tz/people/${id}`,
|
||||||
description: `${nickname} - 旅法师营地`,
|
|
||||||
item: items,
|
item: items,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1,16 +1,21 @@
|
|||||||
const cheerio = require('cheerio');
|
const cheerio = require('cheerio');
|
||||||
const got = require('@/utils/got');
|
const got = require('@/utils/got');
|
||||||
const md5 = require('@/utils/md5');
|
const md5 = require('@/utils/md5');
|
||||||
|
const path = require('path');
|
||||||
|
const { art } = require('@/utils/render');
|
||||||
|
|
||||||
const rootUrl = 'https://www.iyingdi.com';
|
const rootUrl = 'https://www.iyingdi.com';
|
||||||
const ProcessFeed = async (ctx, item) => {
|
|
||||||
const infoUrL = 'https://api.iyingdi.com/web/post/info';
|
const infoUrL = 'https://api.iyingdi.com/web/post/info';
|
||||||
|
|
||||||
|
const ProcessFeed = async (cache, articleList) => {
|
||||||
|
const items = await Promise.all(
|
||||||
|
articleList.map((item) =>
|
||||||
|
cache.tryGet(item.link, async () => {
|
||||||
const infoForm = {
|
const infoForm = {
|
||||||
post_id: item.postId,
|
post_id: item.postId,
|
||||||
timestamp: '',
|
timestamp: '',
|
||||||
};
|
};
|
||||||
const description = await ctx.cache.tryGet(item.link, async () => {
|
const { body } = await got({
|
||||||
const response = await got({
|
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: infoUrL,
|
url: infoUrL,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -20,15 +25,18 @@ const ProcessFeed = async (ctx, item) => {
|
|||||||
Platform: 'pc',
|
Platform: 'pc',
|
||||||
Referer: `${rootUrl}/`,
|
Referer: `${rootUrl}/`,
|
||||||
},
|
},
|
||||||
form: getForm(infoForm),
|
form: ProcessForm(infoForm),
|
||||||
});
|
});
|
||||||
return cleanHtml(JSON.parse(response.body).post.content);
|
item.description = cleanHtml(JSON.parse(body).post.content);
|
||||||
});
|
|
||||||
item.description = description;
|
|
||||||
delete item.postId;
|
|
||||||
return item;
|
return item;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return items;
|
||||||
};
|
};
|
||||||
const getForm = function (form, type) {
|
|
||||||
|
const ProcessForm = (form, type) => {
|
||||||
const key = type ? '8a11ed3712b699e749185674f1dc20b4' : 'b8d5b38577b8bb382b0c783b474b95f9';
|
const key = type ? '8a11ed3712b699e749185674f1dc20b4' : 'b8d5b38577b8bb382b0c783b474b95f9';
|
||||||
form.key = key;
|
form.key = key;
|
||||||
form.timestamp = Math.floor(new Date().getTime() / 1000);
|
form.timestamp = Math.floor(new Date().getTime() / 1000);
|
||||||
@@ -37,16 +45,23 @@ const getForm = function (form, type) {
|
|||||||
return form;
|
return form;
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanHtml = function (htmlString) {
|
const cleanHtml = (htmlString) => {
|
||||||
const regex = new RegExp('(<p>|<div>)(.*?)?<strong>(标准|狂野)日报投稿.*?</strong>(.*?)?(</p>|</div>)(.|\n)*$');
|
const regex = new RegExp('(<p>|<div>)(.*?)?<strong>(标准|狂野)日报投稿.*?</strong>(.*?)?(</p>|</div>)(.|\n)*$');
|
||||||
const $ = cheerio.load(htmlString.replace(regex, ''));
|
const $ = cheerio.load(htmlString.replace(regex, ''));
|
||||||
|
|
||||||
$('.yingdi-car,.bbspost,.deck-set').each((i, e) => {
|
$('.yingdi-car,.bbspost,.deck-set').each((i, e) => {
|
||||||
const className = $(e).attr('class');
|
const className = $(e).attr('class');
|
||||||
const dataId = $(e).attr('data-id');
|
const dataId = $(e).attr('data-id');
|
||||||
const decksUrl = `${rootUrl}/web/tools/hearthstone/decks/setdetail?setid=${dataId}`;
|
const decksUrl = `${rootUrl}/web/tools/hearthstone/decks/setdetail?setid=${dataId}`;
|
||||||
const url = className === 'yingdi-card bbspost' ? `${rootUrl}/tz/post/${dataId}` : decksUrl;
|
const url = className === 'yingdi-card bbspost' ? `${rootUrl}/tz/post/${dataId}` : decksUrl;
|
||||||
|
const time = $(e).find('.card-status .time').text();
|
||||||
|
$(e)
|
||||||
|
.find('.card-info .title')
|
||||||
|
.text((i, c) => `${c} ${time}`);
|
||||||
$(e).find('.card-status').remove();
|
$(e).find('.card-status').remove();
|
||||||
$(e).find('.card-info').wrap(`<a href = "${url}"></a>`);
|
$(e)
|
||||||
|
.find('.card-info')
|
||||||
|
.wrap(art(path.join(__dirname, 'templates/card.art'), { url }));
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.yingdi-image.gif').each((i, e) => {
|
$('.yingdi-image.gif').each((i, e) => {
|
||||||
@@ -60,7 +75,10 @@ const cleanHtml = function (htmlString) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 用户头像
|
// 用户头像
|
||||||
$('.yingdi-card.user').remove();
|
$('.yingdi-card.user').each((i, e) => {
|
||||||
|
$(e).prev('p').remove();
|
||||||
|
$(e).remove();
|
||||||
|
});
|
||||||
// 套牌代码复制
|
// 套牌代码复制
|
||||||
$('.action-button').remove();
|
$('.action-button').remove();
|
||||||
// 投票
|
// 投票
|
||||||
@@ -70,6 +88,6 @@ const cleanHtml = function (htmlString) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getForm,
|
ProcessForm,
|
||||||
ProcessFeed,
|
ProcessFeed,
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user