I haven’t picked up a pen to write for a long time, which also means that I haven’t fooled around with the Copy method for a long time. Who am I? Who I am is not important, river’s lake certainly did not Copy the legend of attacking city lion, however, perhaps this is a true feeling exposed to step on pit article. Before, I had heard “If I have seen further,it is by standing on the shoulders of giants.” Now I was standing on the shoulders of Ryan Dahl and the classy ones. Experience everything Serverless Serverless Deno, from zero to one kao and bei, however, the aluminum friend Rainbow fart bot has no use (currently just sends timed emails).

Pseudo requirements analysis

  1. The best love is THAT I know TA cold and warm, I understand TA mind – regular weather forecast plus chicken soup for the soul;
  2. The best company is to count down the most important day with TA – countdown reminder;
  3. The best mood is TA every day opened his eyes for the first time to see my greetings, the sunset in my good night sound into sleep – good morning good night greetings;
  4. Of course, the most important thing is to learn about new things, such as Deno and Serverless.

Realize the idea

  1. Due to the big guy’s ideas and code implementation, so the code does not have to consider too much, just copy;
  2. Mailbox service directly Github search a wave, now the young people do not speak martial virtue, what database, secret key, mailbox account password, company project source code and so on all lost to Github, I also want to Kangkang (do not know whether will drink tea);
  3. Think about the code implementation, when it comes to date and time calculations and email, do you need a giant shoulder pad? The plugins are just here!
  4. How do you deploy it? After a slight comparison, the cloud of goose factory seems to support the deployment of Deno several months ago, should be more mature (did not expect to fall into the pit).
  5. Finally, Just Do IT!

steaming

Did you guess something disgusting from the headlines? Yes, it is! After 99, 81 minutes of browsing through various API documents (mostly stuck in the Serverless section), the new code with interesting eyes came out after several twists and turns:

/*
* Copyer huqi
* https://github.com/hu-qi
*/
import * as log from "https://deno.land/[email protected]/log/mod.ts";
import { SmtpClient } from "https://deno.land/x/smtp/mod.ts";
import {
  differenceInDays,
  format,
} from "https://deno.land/x/[email protected]/index.js";
import { zhCN } from "https://deno.land/x/[email protected]/locale/index.js";
import "https://deno.land/x/dotenv/load.ts";

// An arbitrary entry from.env
const {
  SEND_EMAIL,
  PASSWORD,
  RECV_EMAIL,
  NAME_GIRL,
  CITY,
  CUTDOWNDATE,
  CUTDOWNTHINGS,
} = Deno.env.toObject();

// Very casual API, from nuggets
const URL = {
  weather: `http://wthrcdn.etouch.cn/weather_mini?city=${CITY}`.soup: "https://www.iowen.cn/jitang/api/".pi: "https://chp.shadiao.app/api.php"};// Configure the email service first, regardless of whether it works
const client = new SmtpClient();

const connectConfig: any = {
  hostname: "smtp.163.com".port: 25.username: SEND_EMAIL,
  password: PASSWORD,
};

// We assume that all returns are structured data
async function _html(url: string) :Promise<string> {
  return await (await fetch(url)).text();
}

// The weather in the target city
async function getWeather(url: string) {
  let data = await _html(url);
  if (data.indexOf("OK") > -1) {
    let _data = JSON.parse(data).data;
    const { ganmao, wendu, forecast } = _data;
    const weather = forecast[0].type;
    return ` weather:${weather}Current temperature:${wendu}
          ${ganmao}`;
  } else {
    return "What wonderful weather today, my dear!"; }}/ / the countdown
function getTime() {
  const today = format(new Date(), "PPPP", { locale: zhCN });
  const days = differenceInDays(new Date(CUTDOWNDATE), new Date());

  return ` today is${today} ${CUTDOWNTHINGS}The countdown:${days}Day `;
}

// Chicken soup for the soul
async function getSoup(url: string) {
  let data = await _html(url);
  if (data.indexOf("Data acquisition success") > -1) {
    let _data = JSON.parse(data).data;
    const { content } = _data.content;
    return content;
  } else {
    return 'The college entrance examination was yesterday,${CUTDOWNTHINGS}In tomorrow, today is nothing! `; }}// rainbow 🌈 fart?
async function getPi(url: string) {
  let data = await _html(url);
  return data.length > 3 ? data : "You must have been a soda in your last life. Why do I bubbly when I see you?";
}

Good morning / /
async function morning() {
  return `
          <p>${getTime()}</p>
          <p>The ${await getSoup(URL.soup)} </p>
          <p>The ${await getWeather(URL.weather)} </p>
          <p>The ${await getPi(URL.pi)}</p>
      `;
}

/ / good night
async function ngiht() {
  return `
          <p>The ${await getSoup(URL.soup)} </p>
          <p>The ${await getPi(URL.pi)}</p> <p> Good night,${NAME_GIRL}Students, today you are the best, continue to come on duck! </p> `;
}

// The date plugin is kinda cool
function getTimeX() {
  // Return "morning" or "afternoon"
  return format(new Date(), "aaaa", { locale: zhCN });
}

// the entry function
async function main_handler() {
  // The body of the message
  const content = getTimeX() === "Morning" ? await morning() : await ngiht();
  // The subject of the email
  const greeting = getTimeX() === "Morning"
    ? Good morning `,${NAME_GIRL}`
    : ` good night.${NAME_GIRL} `;

  // "Keep an eye out for possible errors"
  try {
    await client.connect(connectConfig);
    await client.send({
      from: SEND_EMAIL,
      to: RECV_EMAIL,
      subject: greeting,
      content: content,
    });
    await client.close();
    log.info("send email success");
  } catch (error) {
    // "Now proceed to Plan B ",
    // "Instead of worrying about the abnormality of the program, pay more attention to the girl around you"
    log.error(error);
    log.info("Error: send email fail");
  }
  log.info(content);
  return content;
}

// Execute immediately.
main_handler();
Copy the code

Have to sigh Deno’s ecology is really awesome, want to use what plug-in what plug-in, just meet so many requirements above. Like this date library, very rich, whether it is date formatting, internationalization or date commonly used functions and so on, considered very thoughtful, like so easy to use plug-ins, Copy siege lion don’t learn, I am not to learn, this life is impossible to learn.

Frozen wanli

The first night is called the first night, the first snow is called the first snow, the news said that many parts of the country ushered in the first snow these days, I also felt the intermittent chill in Guangzhou, last night I felt like sleeping in the street, the winter wind blowing, it seemed to laugh at my weak blowing technology, pa pa fan me the whole night…… Fortunately, after Tencent cloud engineers, I woke up like a dream, finally out of the “thousands of miles of ice, thousands of miles of snow floating”, ushered in the joy of successful deployment.

Let’s talk about the process of deploying Deno cloud functions:

  1. Firstly, it is clear that both Tencent Cloud function and Cloud development CloudBase support the deployment of Deno application. After exploring, I think the current bot is more suitable for cloud function, so we deploy Deno by creating a new cloud function.
  2. In the new cloud function, we first choose template function -Deno to create, mainly because we need the code provided by the official template and Deno and bootrap command tools; Then don’t change, the template code directly to the download to a local, etc, we put large files such as deno in function of cloud layer, because there is a “crater” – the official template code and command line tools total size over the cloud functions required by the online editing mode 10 m, so does not support online editor (like automatically generates the environment and the code to us, But you can’t change it directly);
  3. In view of the “pit”, we think of way is to download the code (environment) to local, upload large files as layer (actually the file called deno alone as a layer is enough, accounted for more than 50 M, also can put some deno depend on the packet layer), and then put the rest of the code file upload function can avoid pit;
  4. There is also a “hole”, it is I can’t find home, technology not relative knowledge of cloud function, as if this cloud function must have a return to calculate the call is successful, although call failure can also perform the entry function, but has always been a timeout error), after screening, coupled with the official templates about the event triggered a series of code can call the normal,
  5. Another thing that feels very practical isThe environment variableThat cloud functionFunction configurationEnvironment variable key value pair set in the code can passDeno.env.toObject()Capture; Of course,Test eventsParticipate in the official transfer in templates provide code can also capture, thus do the simple configuration, change the environment variables or output event parameters, I can send other aluminum “friend” warm heart of mail, even can configure a 10 “aluminum friends”, at the same time send mail, love spell will win!

No pictures of a

In order to fill these “pits”, I almost with the goose factory engineer against the bug, but not the big guy, otherwise I do not speak wude, in the big guy’s love to explain and patiently answer, I can only rat tail juice, bitterly left! When I was young, there was a legend of “no picture to tell” in rivers and lakes. Now THAT I am old, thanks to the work order system of cloud platform, I can also carry out “communication between storming lions and engineers” with engineers from various big factories.

To avoid this, I removed the last line of the immediate function and added the following code in the official template, which captures the trigger function arguments:

// do initialize
const scf_host: string | undefined = Deno.env.get("SCF_RUNTIME_API");

const scf_port: string | undefined = Deno.env.get("SCF_RUNTIME_API_PORT");

const func_name: string | undefined = Deno.env.get("_HANDLER");

const ready_url = `http://${scf_host}:${scf_port}/runtime/init/ready`;

const event_url = `http://${scf_host}:${scf_port}/runtime/invocation/next`;

const response_url =
  `http://${scf_host}:${scf_port}/runtime/invocation/response`;

const error_url = `http://${scf_host}:${scf_port}/runtime/invocation/error`;

// post ready -- finish initialization
console.log(`post ${ready_url}`);

postData(ready_url, { msg: "deno ready" }).then((data) = > {
  console.log(`Initialize finish`);
});

async function processEvent(evt=' ') {
  if (evt.length === 0) {
    postData(error_url, {msg: "error handling event"}).then(data= > {
      console.log(`Error response: ${data}`);
    });
  } else {
    postData(response_url, {msg:`finish process event`}).then(data= > {
      console.log(`invoke response: ${data}`); }); }}// Example POST method implementation:
async function postData(url = ' ', data = {}) {
  // Default options are marked with *
  const response = await fetch(url, {
    method: 'POST'.// *GET, POST, PUT, DELETE, etc.
    body: JSON.stringify(data) // body data type must match "Content-Type" header
  });
  return response.text(); // parses JSON response into native JavaScript objects
}

while (true) {
  // get event
  // Execute the suspension immediately
  const responseEmail = await main_handler();
  const response = await fetch(event_url);
  response.text().then(function(text) {
    console.log(`get event: ${text}`);
    processEvent(text);
  });
}
Copy the code

It’s worth mentioning the file provided by the official template. Here’s a screenshot of the infamous deno file, which is over 50 MB in size and makes it impossible to modify the online code in a friendly way:

If this deployment is successful,layerThe first step in this process, I understand, is that large files such as node_modules of NodeJS need to be placedlayerIn theory, Deno dependency package is the same, fortunately, Deno dependency is lighter.

Second, according to the official documentation “the files in the layer will be added to the /opt directory, which is accessible during function execution”, we will start the file slightly modified:

In addition, is our “aluminum friend” configuration, enter as you like, see how you want to use how to define, finished the code is OK:

However, when it comes to time zone issues, you’ll have to put them on hold:

Hope everybody big guy can answer once!

Finally, attach the code of Copy, welcome your advice: Hu-Qi /deno-serverless

🏆 issue 7 | all things can be Serverless technology projects