slack 업데이트

This commit is contained in:
build@lguplus.co.kr 2023-12-08 16:03:24 +09:00
parent 0be273f225
commit c59bccf805
4 changed files with 289 additions and 179 deletions

View file

@ -1,113 +1,136 @@
// ignore_for_file: non_constant_identifier_names, avoid_init_to_null, constant_identifier_names
// ignore: depend_on_referenced_packages, implementation_imports
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:json_annotation/json_annotation.dart';
import 'package:http/http.dart';
// ignore: depend_on_referenced_packages, implementation_imports
import 'package:http_parser/src/media_type.dart';
part 'slack_data.g.dart';
enum SlackBlockType { header, section }
enum SlackBlockType { header, section, divider, actions }
enum SlackTextType { mrkdwn, plain_text }
enum SlackActionType { button, select }
enum SlackActionType { button, select, image }
enum SlackActionStyle { danger, primary }
@JsonSerializable()
class DataSlack {
String? message;
List<SlackBlock> blocks = [];
List<SlackAttachment> attachments = [];
String channel;
String? text;
late List<SlackBlock>? blocks = null;
late List<SlackAttachment>? attachments = null;
bool? link_names;
String getBlocks() {
var list = [];
for (var item in blocks) {
list.add(item.toJson());
}
return jsonEncode(list);
String get json
{
return jsonEncode(toJson());
}
String getAttachments() {
var list = [];
for (var item in attachments) {
list.add(item.toJson());
}
return jsonEncode(list);
}
DataSlack();
DataSlack(this.channel);
factory DataSlack.fromJson(Map<String, dynamic> json) =>
_$DataSlackFromJson(json);
Map<String, dynamic> toJson() => _$DataSlackToJson(this);
Map<String, dynamic> toJson() {
return removeKeys(_$DataSlackToJson(this));
}
}
Map<String, dynamic> removeKeys(Map<String, dynamic> map)
{
var emptyKeys = [];
for(var item in map.entries) {
if(item.value == null) {
emptyKeys.add(item.key);
}
if(item.value is List) {
var list = item.value as List;
if(list.isEmpty) {
emptyKeys.add(item.key);
}
}
}
for(var key in emptyKeys) {
map.remove(key);
}
return map;
}
@JsonSerializable()
class SlackBlock {
late SlackBlockType type;
late String? block_id = null;
SlackBlock();
factory SlackBlock.fromJson(Map<String, dynamic> json) =>
_$SlackBlockFromJson(json);
Map<String, dynamic> toJson() => _$SlackBlockToJson(this);
Map<String, dynamic> toJson() => removeKeys(_$SlackBlockToJson(this));
}
@JsonSerializable()
class SlackBlockHeader extends SlackBlock {
late SlackBlockText text;
late SlackBlockText? text;
SlackBlockHeader() {
super.type = SlackBlockType.header;
text = SlackBlockText();
text.type = SlackTextType.plain_text;
}
factory SlackBlockHeader.fromJson(Map<String, dynamic> json) =>
_$SlackBlockHeaderFromJson(json);
@override
Map<String, dynamic> toJson() => _$SlackBlockHeaderToJson(this);
Map<String, dynamic> toJson() => removeKeys(_$SlackBlockHeaderToJson(this));
}
@JsonSerializable()
class SlackBlockSection extends SlackBlock {
List<SlackBlockSectionField> fields = [];
late SlackBlockText? text = null;
late List<SlackBlockText>? fields = null;
late SlackAccessory? accessory = null;
SlackBlockSection() {
super.type = SlackBlockType.section;
SlackBlockSection()
{
type = SlackBlockType.section;
}
factory SlackBlockSection.fromJson(Map<String, dynamic> json) =>
_$SlackBlockSectionFromJson(json);
@override
Map<String, dynamic> toJson() => _$SlackBlockSectionToJson(this);
Map<String, dynamic> toJson() => removeKeys(_$SlackBlockSectionToJson(this));
}
@JsonSerializable()
class SlackBlockSectionField {
SlackTextType type = SlackTextType.mrkdwn;
String? text;
class SlackAccessory {
late SlackActionType type;
late SlackBlockText? text = null;
late String? image_url = null;
late String? alt_text = null;
late String? value = null;
late String? url = null;
SlackBlockSectionField();
SlackAccessory();
factory SlackBlockSectionField.fromJson(Map<String, dynamic> json) =>
_$SlackBlockSectionFieldFromJson(json);
Map<String, dynamic> toJson() => _$SlackBlockSectionFieldToJson(this);
factory SlackAccessory.fromJson(Map<String, dynamic> json) =>
_$SlackAccessoryFromJson(json);
Map<String, dynamic> toJson() => removeKeys(_$SlackAccessoryToJson(this));
}
@JsonSerializable()
class SlackBlockText {
SlackTextType type = SlackTextType.mrkdwn;
String? text;
late String? text = null;
late bool? emoji = null;
SlackBlockText();
factory SlackBlockText.fromJson(Map<String, dynamic> json) =>
_$SlackBlockTextFromJson(json);
Map<String, dynamic> toJson() => _$SlackBlockTextToJson(this);
Map<String, dynamic> toJson() => removeKeys(_$SlackBlockTextToJson(this));
}
@JsonSerializable()
@ -127,27 +150,29 @@ class SlackAttachment {
String? footer_icon;
String? ts;
List<SlackField>? fields;
List<SlackAction>? actions;
late List<SlackBlock>? blocks = null;
late List<SlackField>? fields = null;
late List<SlackAction>? actions = null;
SlackAttachment();
factory SlackAttachment.fromJson(Map<String, dynamic> json) =>
_$SlackAttachmentFromJson(json);
Map<String, dynamic> toJson() => _$SlackAttachmentToJson(this);
Map<String, dynamic> toJson() => removeKeys(_$SlackAttachmentToJson(this));
}
@JsonSerializable()
class SlackField {
String? title;
String? value;
bool? short = false;
SlackField();
SlackField.withParam(this.title, this.value);
SlackField.withParam(this.title, this.value, {this.short});
factory SlackField.fromJson(Map<String, dynamic> json) =>
_$SlackFieldFromJson(json);
Map<String, dynamic> toJson() => _$SlackFieldToJson(this);
Map<String, dynamic> toJson() => removeKeys(_$SlackFieldToJson(this));
}
@JsonSerializable()
@ -167,22 +192,19 @@ class SlackAction {
factory SlackAction.fromJson(Map<String, dynamic> json) =>
_$SlackActionFromJson(json);
Map<String, dynamic> toJson() => _$SlackActionToJson(this);
Map<String, dynamic> toJson() => removeKeys(_$SlackActionToJson(this));
}
@JsonSerializable()
class SlackConfirm {
String? title;
String? text;
// ignore: non_constant_identifier_names
String? ok_text;
// ignore: non_constant_identifier_names
String? dismiss_text;
}
class SlackFile {
String? title;
// ignore: non_constant_identifier_names
String? initial_comment;
String? fileName;
String? mimeType;

View file

@ -6,70 +6,119 @@ part of 'slack_data.dart';
// JsonSerializableGenerator
// **************************************************************************
DataSlack _$DataSlackFromJson(Map<String, dynamic> json) => DataSlack()
..message = json['message'] as String?
..blocks = (json['blocks'] as List<dynamic>)
.map((e) => SlackBlock.fromJson(e as Map<String, dynamic>))
.toList()
..attachments = (json['attachments'] as List<dynamic>)
.map((e) => SlackAttachment.fromJson(e as Map<String, dynamic>))
.toList();
DataSlack _$DataSlackFromJson(Map<String, dynamic> json) => DataSlack(
json['channel'] as String,
)
..text = json['text'] as String?
..blocks = (json['blocks'] as List<dynamic>?)
?.map((e) => SlackBlock.fromJson(e as Map<String, dynamic>))
.toList()
..attachments = (json['attachments'] as List<dynamic>?)
?.map((e) => SlackAttachment.fromJson(e as Map<String, dynamic>))
.toList()
..link_names = json['link_names'] as bool?;
Map<String, dynamic> _$DataSlackToJson(DataSlack instance) => <String, dynamic>{
'message': instance.message,
'channel': instance.channel,
'text': instance.text,
'blocks': instance.blocks,
'attachments': instance.attachments,
'link_names': instance.link_names,
};
SlackBlock _$SlackBlockFromJson(Map<String, dynamic> json) =>
SlackBlock()..type = $enumDecode(_$SlackBlockTypeEnumMap, json['type']);
SlackBlock _$SlackBlockFromJson(Map<String, dynamic> json) => SlackBlock()
..type = $enumDecode(_$SlackBlockTypeEnumMap, json['type'])
..block_id = json['block_id'] as String?;
Map<String, dynamic> _$SlackBlockToJson(SlackBlock instance) =>
<String, dynamic>{
'type': _$SlackBlockTypeEnumMap[instance.type]!,
'block_id': instance.block_id,
};
const _$SlackBlockTypeEnumMap = {
SlackBlockType.header: 'header',
SlackBlockType.section: 'section',
SlackBlockType.divider: 'divider',
SlackBlockType.actions: 'actions',
};
SlackBlockHeader _$SlackBlockHeaderFromJson(Map<String, dynamic> json) =>
SlackBlockHeader()
..type = $enumDecode(_$SlackBlockTypeEnumMap, json['type'])
..text = SlackBlockText.fromJson(json['text'] as Map<String, dynamic>);
..block_id = json['block_id'] as String?
..text = json['text'] == null
? null
: SlackBlockText.fromJson(json['text'] as Map<String, dynamic>);
Map<String, dynamic> _$SlackBlockHeaderToJson(SlackBlockHeader instance) =>
<String, dynamic>{
'type': _$SlackBlockTypeEnumMap[instance.type]!,
'block_id': instance.block_id,
'text': instance.text,
};
SlackBlockSection _$SlackBlockSectionFromJson(Map<String, dynamic> json) =>
SlackBlockSection()
..type = $enumDecode(_$SlackBlockTypeEnumMap, json['type'])
..fields = (json['fields'] as List<dynamic>)
.map(
(e) => SlackBlockSectionField.fromJson(e as Map<String, dynamic>))
.toList();
..block_id = json['block_id'] as String?
..text = json['text'] == null
? null
: SlackBlockText.fromJson(json['text'] as Map<String, dynamic>)
..fields = (json['fields'] as List<dynamic>?)
?.map((e) => SlackBlockText.fromJson(e as Map<String, dynamic>))
.toList()
..accessory = json['accessory'] == null
? null
: SlackAccessory.fromJson(json['accessory'] as Map<String, dynamic>);
Map<String, dynamic> _$SlackBlockSectionToJson(SlackBlockSection instance) =>
<String, dynamic>{
'type': _$SlackBlockTypeEnumMap[instance.type]!,
'block_id': instance.block_id,
'text': instance.text,
'fields': instance.fields,
'accessory': instance.accessory,
};
SlackBlockSectionField _$SlackBlockSectionFieldFromJson(
Map<String, dynamic> json) =>
SlackBlockSectionField()
..type = $enumDecode(_$SlackTextTypeEnumMap, json['type'])
..text = json['text'] as String?;
SlackAccessory _$SlackAccessoryFromJson(Map<String, dynamic> json) =>
SlackAccessory()
..type = $enumDecode(_$SlackActionTypeEnumMap, json['type'])
..text = json['text'] == null
? null
: SlackBlockText.fromJson(json['text'] as Map<String, dynamic>)
..image_url = json['image_url'] as String?
..alt_text = json['alt_text'] as String?
..value = json['value'] as String?
..url = json['url'] as String?;
Map<String, dynamic> _$SlackBlockSectionFieldToJson(
SlackBlockSectionField instance) =>
Map<String, dynamic> _$SlackAccessoryToJson(SlackAccessory instance) =>
<String, dynamic>{
'type': _$SlackActionTypeEnumMap[instance.type]!,
'text': instance.text,
'image_url': instance.image_url,
'alt_text': instance.alt_text,
'value': instance.value,
'url': instance.url,
};
const _$SlackActionTypeEnumMap = {
SlackActionType.button: 'button',
SlackActionType.select: 'select',
SlackActionType.image: 'image',
};
SlackBlockText _$SlackBlockTextFromJson(Map<String, dynamic> json) =>
SlackBlockText()
..type = $enumDecode(_$SlackTextTypeEnumMap, json['type'])
..text = json['text'] as String?
..emoji = json['emoji'] as bool?;
Map<String, dynamic> _$SlackBlockTextToJson(SlackBlockText instance) =>
<String, dynamic>{
'type': _$SlackTextTypeEnumMap[instance.type]!,
'text': instance.text,
'emoji': instance.emoji,
};
const _$SlackTextTypeEnumMap = {
@ -77,17 +126,6 @@ const _$SlackTextTypeEnumMap = {
SlackTextType.plain_text: 'plain_text',
};
SlackBlockText _$SlackBlockTextFromJson(Map<String, dynamic> json) =>
SlackBlockText()
..type = $enumDecode(_$SlackTextTypeEnumMap, json['type'])
..text = json['text'] as String?;
Map<String, dynamic> _$SlackBlockTextToJson(SlackBlockText instance) =>
<String, dynamic>{
'type': _$SlackTextTypeEnumMap[instance.type]!,
'text': instance.text,
};
SlackAttachment _$SlackAttachmentFromJson(Map<String, dynamic> json) =>
SlackAttachment()
..fallback = json['fallback'] as String?
@ -104,6 +142,9 @@ SlackAttachment _$SlackAttachmentFromJson(Map<String, dynamic> json) =>
..footer = json['footer'] as String?
..footer_icon = json['footer_icon'] as String?
..ts = json['ts'] as String?
..blocks = (json['blocks'] as List<dynamic>?)
?.map((e) => SlackBlock.fromJson(e as Map<String, dynamic>))
.toList()
..fields = (json['fields'] as List<dynamic>?)
?.map((e) => SlackField.fromJson(e as Map<String, dynamic>))
.toList()
@ -127,18 +168,21 @@ Map<String, dynamic> _$SlackAttachmentToJson(SlackAttachment instance) =>
'footer': instance.footer,
'footer_icon': instance.footer_icon,
'ts': instance.ts,
'blocks': instance.blocks,
'fields': instance.fields,
'actions': instance.actions,
};
SlackField _$SlackFieldFromJson(Map<String, dynamic> json) => SlackField()
..title = json['title'] as String?
..value = json['value'] as String?;
..value = json['value'] as String?
..short = json['short'] as bool?;
Map<String, dynamic> _$SlackFieldToJson(SlackField instance) =>
<String, dynamic>{
'title': instance.title,
'value': instance.value,
'short': instance.short,
};
SlackAction _$SlackActionFromJson(Map<String, dynamic> json) => SlackAction()
@ -159,11 +203,6 @@ Map<String, dynamic> _$SlackActionToJson(SlackAction instance) =>
'style': _$SlackActionStyleEnumMap[instance.style],
};
const _$SlackActionTypeEnumMap = {
SlackActionType.button: 'button',
SlackActionType.select: 'select',
};
const _$SlackActionStyleEnumMap = {
SlackActionStyle.danger: 'danger',
SlackActionStyle.primary: 'primary',

View file

@ -1,6 +1,9 @@
// ignore_for_file: unused_local_variable
import 'dart:async';
import 'package:color/color.dart';
import 'package:dart_framework/utils/system_util.dart';
import 'package:http/http.dart' as http;
import 'slack_data.dart';
@ -10,80 +13,56 @@ enum SlackBuildType { android, ios, windows, mac, web }
class SlackSender {
//Bot TOKEN
final token = "xoxb-291006091297-QT2K1PCpwyX4b5wKk3AQew2G";
String token = "xoxb-291006091297-QT2K1PCpwyX4b5wKk3AQew2G";
//API - https://api.slack.com/methods/chat.postMessage
final urlMessagePost = "https://slack.com/api/chat.postMessage";
//API - https://api.slack.com/methods/files.upload
final urlFileUplaod = "https://slack.com/api/files.upload";
SlackSender(String? token) {
if(token != null) {
this.token = token;
}
}
String getValidatedUser(String? targetUser) {
targetUser ??= "@channel";
targetUser ??= "@here";
if (targetUser.indexOf("@") != 0) targetUser = "@$targetUser";
return targetUser;
}
String getURL(String channel, DataSlack message, String? targetUser,
{bool includeURL = true}) {
targetUser = getValidatedUser(targetUser);
var buffer = StringBuffer();
if (includeURL) {
buffer.write(urlMessagePost);
buffer.write('?');
}
buffer.write('token=$token');
buffer.write('&channel=$channel');
var sendMessage = message.message == null
? ''
: Uri.encodeComponent(' ${message.message!}');
buffer.write('&text=$targetUser$sendMessage');
if (message.blocks.isNotEmpty) {
var json = message.getBlocks();
print(json);
buffer.write('&blocks=${Uri.encodeComponent(message.getBlocks())}');
}
if (message.attachments.isNotEmpty) {
buffer.write(
'&attachments=${Uri.encodeComponent(message.getAttachments())}');
}
buffer.write('&link_names=true');
print(buffer.toString());
return buffer.toString();
}
// Attachment로
Future send(String channel, SlackAttachment attachment,
{String? targetUser,
Function(String)? completeListener,
Function(Exception)? errorListener}) async {
var data = DataSlack();
data.attachments = [attachment];
return await sends(channel, data, targetUser: targetUser);
}
// Attachment로
Future sends(String channel, DataSlack message,
{String? targetUser,
Function(String)? completeListener,
Future send(DataSlack message,
{Function(String)? completeListener,
Function(Object)? errorListener}) async {
var c = Completer();
String url = getURL(channel, message, targetUser);
String url = urlMessagePost;
var response = await http.get(Uri.parse(url));
var header =
{
'Content-Type': 'application/json',
'Authorization': 'Bearer $token'
};
var body = message.json;
print(body);
var response = await http.post(Uri.parse(url), headers: header, body: message.json);
print(response.statusCode);
if (response.statusCode < 300 && response.statusCode >= 200) {
print(response.body);
if (completeListener != null) completeListener(response.body);
if (completeListener != null)
{
completeListener(response.body);
print(response.body);
}
} else {
if (errorListener != null) errorListener(response);
if (errorListener != null)
{
errorListener(response);
print(response.body);
}
}
c.complete();
return c.future;
}
String getParameters(String channel, DataSlack message,
{String? targetUser}) {
return getURL(channel, message, targetUser, includeURL: false);
return simpleFuture;
}
/// ****************** File Send *******************
@ -100,7 +79,6 @@ class SlackSender {
{String? targetUser,
Function(String)? completeListener,
Function(Object)? errorListener}) async {
var c = Completer();
var form = getPostForm(urlFileUplaod, channel, targetUser);
form = await file.setFileData(form);
var response = await form.send();
@ -112,36 +90,10 @@ class SlackSender {
if (errorListener != null) errorListener(result);
}
c.complete();
return c.future;
}
/// ****************** Send template *******************
void sendTest() async {
DataSlack message = DataSlack();
message.attachments = [];
var attachment = SlackAttachment();
attachment.author_name = 'toki';
attachment.text = 'This is Test!!';
attachment.color = '#ff2f00';
attachment.fields = [
SlackField.withParam('Test1', 'Value1'),
SlackField.withParam('Test2', 'Value2'),
];
message.attachments.add(attachment);
attachment = SlackAttachment();
attachment.author_name = 'toki';
attachment.text = 'This is Test!!2';
attachment.color = '#0084ff';
attachment.fields = [
SlackField.withParam('Test3', 'Value3'),
SlackField.withParam('Test4', 'Value4'),
];
message.attachments.add(attachment);
await sends('app_notifier', message, targetUser: 'toki');
return simpleFuture;
}
/// ****************** Build Send *******************
Future sendBuild(String appName, SlackBuildType buildType, Color color,
String version, String downloadURL,
{String channel = 'build'}) async {
@ -150,17 +102,17 @@ class SlackSender {
? '${buildURL}android.png'
: '${buildURL}appstore.png';
String projectIcon = "$buildURL$appName/icon.png";
// ignore: unused_local_variable
String emoji =
buildType == SlackBuildType.android ? ":android1: " : ":ios0: ";
String osColor = buildType == SlackBuildType.ios ? "#ED145B" : "#81CA3F";
var message = DataSlack();
var message = DataSlack(channel);
message.attachments = [];
var attachments = message.attachments;
var attachment = SlackAttachment();
attachment.color = color.toHexColor().toCssString();
attachment.fields = [SlackField.withParam(toPascal(appName), null)];
attachments.add(attachment);
attachments?.add(attachment);
var buildTypeStr = buildTypeToString(buildType);
attachment = SlackAttachment();
@ -176,9 +128,9 @@ class SlackSender {
SlackAction.withParam(
'build', 'Download', downloadURL, null, SlackActionType.button, null)
];
attachments.add(attachment);
attachments?.add(attachment);
return await sends(channel, message);
return await send(message);
}
String buildTypeToString(SlackBuildType type) {

View file

@ -0,0 +1,97 @@
import 'package:dart_framework/utils/slack/slack_data.dart';
//Format info
//https://api.slack.com/reference/surfaces/formatting
class SlackTemplate {
static DataSlack getAttachments(String channel) {
DataSlack data = DataSlack(channel);
data.attachments = [];
var attachment = SlackAttachment();
attachment.fallback = 'Plain-text summary of the attachment.';
attachment.color = '#2eb886';
attachment.pretext = 'Optional text that appears above the attachment block';
attachment.author_name = 'Bobby Tables';
attachment.author_link = 'http://flickr.com/bobby/';
attachment.author_icon = 'http://flickr.com/icons/bobby.jpg';
attachment.title = 'Slack API Documentation';
attachment.title_link = 'https://api.slack.com/';
attachment.text = 'Optional text that appears within the attachment';
attachment.fields = [
SlackField.withParam('Priority', 'High', short: false),
];
attachment.image_url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Flat_tick_icon.svg/1024px-Flat_tick_icon.svg.png';
attachment.thumb_url = 'https://cdn-icons-png.flaticon.com/512/3771/3771140.png';
attachment.footer = 'Slack API';
attachment.footer_icon = 'https://platform.slack-edge.com/img/default_application_icon.png';
attachment.ts = '123456789';
data.attachments!.add(attachment);
return data;
}
static DataSlack getBlocks(String channel) {
DataSlack data = DataSlack(channel);
data.attachments = [];
var attachment = SlackAttachment();
data.blocks = [];
var blockSection = SlackBlockSection();
blockSection.text = SlackBlockText();
blockSection.text!.text = 'Danny Torrence left the following review for your property:';
data.blocks!.add(blockSection);
blockSection = SlackBlockSection();
blockSection.text = SlackBlockText();
blockSection.text!.text = '<https://example.com|Overlook Hotel> \n :star: \n Doors had too many axe holes, guest in room 237 was far too rowdy, whole place felt stuck in the 1920s.';
blockSection.accessory = SlackAccessory();
blockSection.accessory!.type = SlackActionType.image;
blockSection.accessory!.image_url = 'https://is5-ssl.mzstatic.com/image/thumb/Purple3/v4/d3/72/5c/d3725c8f-c642-5d69-1904-aa36e4297885/source/256x256bb.jpg';
blockSection.accessory!.alt_text = 'Haunted hotel image';
data.blocks!.add(blockSection);
blockSection = SlackBlockSection();
blockSection.block_id = 'section789';
blockSection.fields = [];
var field = SlackBlockText();
field.text = '*Average Rating*\n1.0';
blockSection.fields!.add(field);
data.blocks!.add(blockSection);
attachment.blocks = [];
blockSection = SlackBlockSection();
blockSection.text = SlackBlockText();
blockSection.text!.text = '*Alternative hotel options*';
attachment.blocks!.add(blockSection);
blockSection = SlackBlockSection();
blockSection.text = SlackBlockText();
blockSection.text!.text = '<https://example.com|Bates Motel> :star::star:';
blockSection.accessory = SlackAccessory();
blockSection.accessory!.type = SlackActionType.button;
blockSection.accessory!.url = 'https://www.google.com';
blockSection.accessory!.text = SlackBlockText();
blockSection.accessory!.text!.type = SlackTextType.plain_text;
blockSection.accessory!.text!.text = 'View';
blockSection.accessory!.text!.emoji = true;
blockSection.accessory!.value = 'view_alternate_1';
attachment.blocks!.add(blockSection);
blockSection = SlackBlockSection();
blockSection.text = SlackBlockText();
blockSection.text!.text = '<https://example.com|The Great Northern Hotel> :star::star::star::star:';
blockSection.accessory = SlackAccessory();
blockSection.accessory!.type = SlackActionType.button;
blockSection.accessory!.url = 'https://www.naver.com';
blockSection.accessory!.text = SlackBlockText();
blockSection.accessory!.text!.type = SlackTextType.plain_text;
blockSection.accessory!.text!.text = 'View';
blockSection.accessory!.text!.emoji = true;
blockSection.accessory!.value = 'view_alternate_2';
attachment.blocks!.add(blockSection);
data.attachments!.add(attachment);
return data;
}
}