mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-07-05 14:21:54 +08:00
feat: telegram mini app open mail from bot (#256)
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import Index from '../views/Index.vue'
|
||||
import UserLogin from '../views/user/UserLogin.vue'
|
||||
import User from '../views/User.vue'
|
||||
import SendMail from '../views/index/SendMail.vue'
|
||||
import Admin from '../views/Admin.vue'
|
||||
import TelegramMail from '../views/telegram/Mail.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
@@ -19,7 +18,11 @@ const router = createRouter({
|
||||
{
|
||||
path: '/admin',
|
||||
component: Admin
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/telegram_mail',
|
||||
component: TelegramMail
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ const { t } = useI18n({
|
||||
enable: 'Enable',
|
||||
telegramAllowList: 'Telegram Allow List',
|
||||
save: 'Save',
|
||||
miniAppUrl: 'Telegram Mini App URL',
|
||||
},
|
||||
zh: {
|
||||
init: '初始化',
|
||||
@@ -31,6 +32,7 @@ const { t } = useI18n({
|
||||
enable: '启用',
|
||||
telegramAllowList: 'Telegram 白名单',
|
||||
save: '保存',
|
||||
miniAppUrl: '电报小程序 URL(请输入你部署的电报小程序网页地址)',
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -63,14 +65,16 @@ const init = async () => {
|
||||
class TelegramSettings {
|
||||
enableAllowList: boolean;
|
||||
allowList: string[];
|
||||
miniAppUrl: string;
|
||||
|
||||
constructor(enableAllowList: boolean, allowList: string[]) {
|
||||
constructor(enableAllowList: boolean, allowList: string[], miniAppUrl: string) {
|
||||
this.enableAllowList = enableAllowList;
|
||||
this.allowList = allowList;
|
||||
this.miniAppUrl = miniAppUrl;
|
||||
}
|
||||
}
|
||||
|
||||
const settings = ref(new TelegramSettings(false, []))
|
||||
const settings = ref(new TelegramSettings(false, [], ''))
|
||||
|
||||
const getSettings = async () => {
|
||||
try {
|
||||
@@ -111,6 +115,9 @@ onMounted(async () => {
|
||||
:placeholder="t('telegramAllowList')" />
|
||||
</n-input-group>
|
||||
</n-form-item-row>
|
||||
<n-form-item-row :label="t('miniAppUrl')">
|
||||
<n-input v-model:value="settings.miniAppUrl"></n-input>
|
||||
</n-form-item-row>
|
||||
<n-button @click="saveSettings" type="primary" block>
|
||||
{{ t('save') }}
|
||||
</n-button>
|
||||
|
||||
@@ -9,6 +9,29 @@ import Turnstile from '../../components/Turnstile.vue'
|
||||
|
||||
import { useGlobalState } from '../../store'
|
||||
import { api } from '../../api'
|
||||
|
||||
const props = defineProps({
|
||||
bindUserAddress: {
|
||||
type: Function,
|
||||
default: async () => { await api.bindUserAddress(); },
|
||||
requried: true
|
||||
},
|
||||
newAddressPath: {
|
||||
type: Function,
|
||||
default: async (address_name, domain, cf_token) => {
|
||||
return await api.fetch("/api/new_address", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
name: address_name,
|
||||
domain: domain,
|
||||
cf_token: cf_token,
|
||||
}),
|
||||
});
|
||||
},
|
||||
requried: true
|
||||
},
|
||||
})
|
||||
|
||||
const message = useMessage()
|
||||
const router = useRouter()
|
||||
|
||||
@@ -32,7 +55,7 @@ const login = async () => {
|
||||
jwt.value = credential.value;
|
||||
await api.getSettings();
|
||||
try {
|
||||
await api.bindUserAddress();
|
||||
await props.bindUserAddress();
|
||||
} catch (error) {
|
||||
message.error(`${t('bindUserAddressError')}: ${error.message}`);
|
||||
}
|
||||
@@ -98,20 +121,17 @@ const generateName = async () => {
|
||||
|
||||
const newEmail = async () => {
|
||||
try {
|
||||
const res = await api.fetch(`/api/new_address`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
name: emailName.value,
|
||||
domain: emailDomain.value,
|
||||
cf_token: cfToken.value,
|
||||
}),
|
||||
});
|
||||
const res = await props.newAddressPath(
|
||||
emailName.value,
|
||||
emailDomain.value,
|
||||
cfToken.value
|
||||
);
|
||||
jwt.value = res["jwt"];
|
||||
await api.getSettings();
|
||||
await router.push("/");
|
||||
showAddressCredential.value = true;
|
||||
try {
|
||||
await api.bindUserAddress();
|
||||
await props.bindUserAddress();
|
||||
} catch (error) {
|
||||
message.error(`${t('bindUserAddressError')}: ${error.message}`);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ const { t } = useI18n({
|
||||
locale: localeCache.value || 'zh',
|
||||
messages: {
|
||||
en: {
|
||||
addressManage: 'Address Manage',
|
||||
changeAddress: 'Change Address',
|
||||
ok: 'OK',
|
||||
copy: 'Copy',
|
||||
@@ -34,6 +35,7 @@ const { t } = useI18n({
|
||||
userLogin: 'User Login',
|
||||
},
|
||||
zh: {
|
||||
addressManage: '地址管理',
|
||||
changeAddress: '更换地址',
|
||||
ok: '确定',
|
||||
copy: '复制',
|
||||
@@ -74,7 +76,7 @@ onMounted(async () => {
|
||||
<b>{{ settings.address }}</b>
|
||||
<n-button v-if="isTelegram" style="margin-left: 10px" @click="showTelegramChangeAddress = true"
|
||||
size="small" tertiary type="primary">
|
||||
<n-icon :component="ExchangeAlt" /> {{ t('changeAddress') }}
|
||||
<n-icon :component="ExchangeAlt" /> {{ t('addressManage') }}
|
||||
</n-button>
|
||||
<n-button v-else-if="userJwt" style="margin-left: 10px" @click="showChangeAddress = true"
|
||||
size="small" tertiary type="primary">
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, h, onMounted } from 'vue';
|
||||
import { useSessionStorage } from '@vueuse/core';
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { NPopconfirm, NButton } from 'naive-ui'
|
||||
|
||||
@@ -8,6 +7,8 @@ import { NPopconfirm, NButton } from 'naive-ui'
|
||||
import { useGlobalState } from '../../store'
|
||||
// @ts-ignore
|
||||
import { api } from '../../api'
|
||||
// @ts-ignore
|
||||
import Login from '../common/Login.vue';
|
||||
|
||||
const { localeCache, jwt, telegramApp } = useGlobalState()
|
||||
// @ts-ignore
|
||||
@@ -21,21 +22,27 @@ const { t } = useI18n({
|
||||
address: 'Address',
|
||||
actions: 'Actions',
|
||||
changeMailAddress: 'Change Mail Address',
|
||||
unbindMailAddress: 'Unbind Mail Address',
|
||||
bind: 'Bind',
|
||||
bindAddressSuccess: 'Bind Address Success',
|
||||
},
|
||||
zh: {
|
||||
success: '成功',
|
||||
address: '地址',
|
||||
actions: '操作',
|
||||
changeMailAddress: '切换邮箱地址',
|
||||
unbindMailAddress: '解绑邮箱地址',
|
||||
bind: '绑定',
|
||||
bindAddressSuccess: '绑定地址成功',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const data = useSessionStorage("telegram-bind-address", [])
|
||||
const data = ref([]);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
data.value = await api.fetch(`/telegram/bind_address`, {
|
||||
data.value = await api.fetch(`/telegram/get_bind_address`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
initData: telegramApp.value.initData
|
||||
@@ -46,6 +53,32 @@ const fetchData = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const newAddressPath = async (address_name: string, domain: string, cf_token: string) => {
|
||||
return await api.fetch("/telegram/new_address", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
initData: telegramApp.value.initData,
|
||||
address: `${address_name}@${domain}`,
|
||||
cf_token: cf_token,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const bindAddress = async () => {
|
||||
try {
|
||||
await api.fetch(`/telegram/bind_address`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
initData: telegramApp.value.initData,
|
||||
jwt: jwt.value
|
||||
})
|
||||
});
|
||||
message.success(t('bindAddressSuccess'));
|
||||
} catch (error) {
|
||||
message.error((error as Error).message || "error");
|
||||
}
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: t('address'),
|
||||
@@ -73,6 +106,31 @@ const columns = [
|
||||
),
|
||||
default: () => `${t('changeMailAddress')}?`
|
||||
}
|
||||
),
|
||||
h(NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => {
|
||||
api.fetch(`/telegram/unbind_address`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
initData: telegramApp.value.initData,
|
||||
address: row.address
|
||||
})
|
||||
});
|
||||
jwt.value = ""
|
||||
location.reload()
|
||||
}
|
||||
},
|
||||
{
|
||||
trigger: () => h(NButton,
|
||||
{
|
||||
tertiary: true,
|
||||
type: "warning",
|
||||
},
|
||||
{ default: () => t('unbindMailAddress') }
|
||||
),
|
||||
default: () => `${t('unbindMailAddress')}?`
|
||||
}
|
||||
)
|
||||
])
|
||||
}
|
||||
@@ -89,6 +147,13 @@ onMounted(async () => {
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<n-data-table :columns="columns" :data="data" :bordered="false" />
|
||||
<n-tabs type="segment">
|
||||
<n-tab-pane name="address" :tab="t('address')">
|
||||
<n-data-table :columns="columns" :data="data" :bordered="false" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="bind" :tab="t('bind')">
|
||||
<Login :newAddressPath="newAddressPath" :bindUserAddress="bindAddress" />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
70
frontend/src/views/telegram/Mail.vue
Normal file
70
frontend/src/views/telegram/Mail.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<script setup>
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { useGlobalState } from '../../store'
|
||||
import { api } from '../../api'
|
||||
import { onMounted, watch } from 'vue';
|
||||
import { processItem } from '../../utils/email-parser'
|
||||
|
||||
const { telegramApp } = useGlobalState()
|
||||
const route = useRoute()
|
||||
|
||||
const curMail = ref({});
|
||||
|
||||
watch(telegramApp, async () => {
|
||||
if (telegramApp.value.initData) {
|
||||
curMail.value = await fetchMailData();
|
||||
}
|
||||
});
|
||||
|
||||
const fetchMailData = async () => {
|
||||
try {
|
||||
const res = await api.fetch(`/telegram/get_mail`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
initData: telegramApp.value.initData,
|
||||
mailId: route.query.mail_id
|
||||
})
|
||||
});
|
||||
return await processItem(res);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
curMail.value = await fetchMailData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="center">
|
||||
<n-card v-if="curMail.message" style="max-width: 800px; overflow: auto;">
|
||||
<n-tag type="info">
|
||||
ID: {{ curMail.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
Date: {{ curMail.created_at }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
FROM: {{ curMail.source }}
|
||||
</n-tag>
|
||||
<n-tag v-if="showEMailTo" type="info">
|
||||
TO: {{ curMail.address }}
|
||||
</n-tag>
|
||||
<div v-html="curMail.message" style="margin-top: 10px;"></div>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.center {
|
||||
display: flex;
|
||||
text-align: left;
|
||||
place-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user