SHA256
Каналы: типы 0/1/100/200, CreateChannel v3, state для chat200, новые API и деплой на prod
This commit is contained in:
@@ -42,7 +42,12 @@ const MSG_SUBTYPE_REACTION_LIKE = 1;
|
||||
const MSG_SUBTYPE_REACTION_UNLIKE = 2;
|
||||
const MSG_SUBTYPE_CONNECTION_FOLLOW = 30;
|
||||
const MSG_SUBTYPE_CONNECTION_UNFOLLOW = 31;
|
||||
const CREATE_CHANNEL_BODY_VERSION = 2;
|
||||
const CREATE_CHANNEL_BODY_VERSION = 3;
|
||||
const CHANNEL_TYPE_STORIES = 0;
|
||||
const CHANNEL_TYPE_PUBLIC = 1;
|
||||
const CHANNEL_TYPE_PERSONAL = 100;
|
||||
const CHANNEL_TYPE_GROUP = 200;
|
||||
const CHANNEL_TYPE_VERSION_DEFAULT = 1;
|
||||
|
||||
const CONNECTION_SUBTYPES = Object.freeze({
|
||||
// Legacy alias: friend == close_friend. Оба ключа ведут на один и тот же код 10/11.
|
||||
@@ -404,13 +409,15 @@ function normalizeChannelDescription(value) {
|
||||
return text;
|
||||
}
|
||||
|
||||
function makeCreateChannelBodyV2Bytes({
|
||||
function makeCreateChannelBodyV3Bytes({
|
||||
lineCode,
|
||||
prevLineNumber,
|
||||
prevLineHashHex,
|
||||
thisLineNumber,
|
||||
channelName,
|
||||
channelDescription = '',
|
||||
channelType = CHANNEL_TYPE_PUBLIC,
|
||||
channelTypeVersion = CHANNEL_TYPE_VERSION_DEFAULT,
|
||||
}) {
|
||||
const check = validateChannelDisplayName(channelName);
|
||||
if (!check.ok) throw new Error(channelNameErrorText(check.code));
|
||||
@@ -426,6 +433,14 @@ function makeCreateChannelBodyV2Bytes({
|
||||
if (descriptionBytes.length > 200) {
|
||||
throw new Error('Описание канала слишком длинное: максимум 200 символов.');
|
||||
}
|
||||
const typeCode = Number(channelType);
|
||||
const typeVer = Number(channelTypeVersion);
|
||||
if (!Number.isFinite(typeCode) || typeCode < 0 || typeCode > 65535) {
|
||||
throw new Error('Некорректный тип канала.');
|
||||
}
|
||||
if (!Number.isFinite(typeVer) || typeVer < 0 || typeVer > 65535) {
|
||||
throw new Error('Некорректная версия типа канала.');
|
||||
}
|
||||
|
||||
return concatBytes(
|
||||
int32Bytes(lineCode),
|
||||
@@ -436,6 +451,8 @@ function makeCreateChannelBodyV2Bytes({
|
||||
nameBytes,
|
||||
int16Bytes(descriptionBytes.length),
|
||||
descriptionBytes,
|
||||
uint16Bytes(typeCode),
|
||||
uint16Bytes(typeVer),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1004,11 +1021,19 @@ export class AuthService {
|
||||
rootBlockNumber: Number(item?.channel?.channelRoot?.blockNumber),
|
||||
rootBlockHash: normalizeHex32(item?.channel?.channelRoot?.blockHash, ZERO64),
|
||||
channelName: String(item?.channel?.channelName || ''),
|
||||
channelTypeCode: Number(item?.channel?.channelTypeCode ?? CHANNEL_TYPE_PUBLIC),
|
||||
}))
|
||||
.filter((item) => Number.isFinite(item.rootBlockNumber) && item.rootBlockNumber >= 0);
|
||||
}
|
||||
|
||||
async addBlockCreateChannel({ login, channelName, channelDescription = '', storagePwd }) {
|
||||
async addBlockCreateChannel({
|
||||
login,
|
||||
channelName,
|
||||
channelDescription = '',
|
||||
channelType = CHANNEL_TYPE_PUBLIC,
|
||||
channelTypeVersion = CHANNEL_TYPE_VERSION_DEFAULT,
|
||||
storagePwd,
|
||||
}) {
|
||||
const cleanLogin = (login || '').trim();
|
||||
if (!cleanLogin) throw new Error('Missing login');
|
||||
|
||||
@@ -1018,7 +1043,9 @@ export class AuthService {
|
||||
const cleanChannelDescription = normalizeChannelDescription(channelDescription);
|
||||
const channelSlug = toCanonicalChannelSlug(cleanChannelName);
|
||||
|
||||
const key = `create-channel:${cleanLogin}:${channelSlug || cleanChannelName.toLowerCase()}`;
|
||||
const typeCode = Number(channelType);
|
||||
const typeVersion = Number(channelTypeVersion);
|
||||
const key = `create-channel:${cleanLogin}:${typeCode}:${channelSlug || cleanChannelName.toLowerCase()}`;
|
||||
return this.runWriteLocked(key, async () => {
|
||||
const user = await this.ensureChainInitializedForLineOps(cleanLogin, storagePwd);
|
||||
const blockchainName = String(user?.blockchainName || `${cleanLogin}-${BCH_SUFFIX}`).trim();
|
||||
@@ -1053,13 +1080,15 @@ export class AuthService {
|
||||
msgType: MSG_TYPE_TECH,
|
||||
msgSubType: MSG_SUBTYPE_TECH_CREATE_CHANNEL,
|
||||
msgVersion: CREATE_CHANNEL_BODY_VERSION,
|
||||
bodyBytes: makeCreateChannelBodyV2Bytes({
|
||||
bodyBytes: makeCreateChannelBodyV3Bytes({
|
||||
lineCode: 0,
|
||||
prevLineNumber,
|
||||
prevLineHashHex,
|
||||
thisLineNumber,
|
||||
channelName: cleanChannelName,
|
||||
channelDescription: cleanChannelDescription,
|
||||
channelType: typeCode,
|
||||
channelTypeVersion: typeVersion,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1099,11 +1128,6 @@ export class AuthService {
|
||||
if (ownerBlockchainName !== blockchainName) {
|
||||
throw new Error('Posting is allowed only to your own channels');
|
||||
}
|
||||
// Канал 0 оставляем как технический root-поток.
|
||||
// Контент-публикации в него временно отключены (пишем только в именованные каналы).
|
||||
if (lineCode === 0) {
|
||||
throw new Error('Публикации в канал 0 временно отключены. Создайте отдельный канал.');
|
||||
}
|
||||
|
||||
let rootHashHex = normalizeHex32(selector?.channelRootBlockHash, ZERO64);
|
||||
if (rootHashHex === ZERO64) {
|
||||
|
||||
Reference in New Issue
Block a user