【个人开发】开发一个每天早上向我发送电力费用的Line Bot,以GraphQL API作为请求方式【第一部分】
起初,首先.
由于我目前使用的Octopus Energy提供了GraphQL API,我打算利用它开发一个每天早上都能收到电费通知的Line Bot。
这一次我们将会讲解Rails与外部API的集成、GraphQL的使用方法以及如何运用Line Messaging API。
关于定期运行和部署,我们计划在下一篇文章中写(尚未实施)。
如果想知道GraphQL到底是什么的话,请查看下面的文章。
利用技术
Rails(API模式):7.0.8
Ruby:3.2.0
graphql 2.0.27
Line Messaging API
实施策略
1.使用Rails调用GraphQL获取电费信息
2.利用Line Messaging API将获取的电费信息发送给用户
— 这次的任务到这里结束 —
3.在开发环境中创建定期执行的任务
4.确保在生产环境中能够定期执行
让Rails通过GraphQL获取并返回电费信息
在使用Octopus Energy获取电费的步骤如下:
1.注册Otopus Energy账户。
2.开始使用Octopus Energy供电。
1-1. 使用电子邮件和密码作为查询变量,获取认证令牌(变更)。
1-2. 使用认证令牌获取电费信息(查询)。
使用Mutation和Query的区别
基本上,它大致上將按照下圖的組合使用來區分。
-
- RESTとはRepresentational State Transferの略でwebサービスの設計モデルのこと
-
- SQLとはデータベース用のクエリ言語のこと
- GraphQLとはAPIのクエリ言語のこと
如果把数据获取称为Query,其他操作称为Mutation,这样可能更容易记忆(另外,事件监控称为Subscription)。
准备事项
在安装 Rails 应用之前,需要通过添加以下 gem 并执行 bundle install 使 Graphql 在 Rails 应用中可用。
gem 'graphql'
gem 'graphql-client'
gem 'dotenv-rails'
graphql-client是一个用于声明、创建和执行GraphQL查询的Ruby库。
请参阅以下内容以获取更详细信息。
dotenv-rails是一个用于管理环境变量的Ruby库。通过在应用程序的根目录下创建.env文件,可以处理不希望在网络上公开的机密密钥和密码等信息,并且可以自动加载这些信息。
OCTOPUS_EMAIL = "XXX@example.com"
OCTOPUS_PASSWORD = "passwordhogefuga"
可以这样定义:
调用时,可以通过类似 ENV[“OCTOPUS_EMAIL”] 的形式进行调用!
为了隐藏文件,请确保设置了.gitignore文件,以防忘记。
请查看以下详细内容。
1-1. 使用电子邮件和密码作为查询变量,获取认证令牌。
在进行了上述的安装之后,为了获取令牌,请创建以下文件。
由于对于graphql-client的补充说明很少,因此我将在注释中进行说明。
require "graphql/client"
require "graphql/client/http"
class OctopusAuthenticationToken
# http アダプターを設定
HTTP = GraphQL::Client::HTTP.new("https://api.oejp-kraken.energy/v1/graphql/")
# 上記を使用して、API サーバーから GraphQL Schema を取得
Schema = GraphQL::Client.load_schema(HTTP)
# 上記を使ってクライアント作成
Client = GraphQL::Client.new(schema: Schema, execute: HTTP)
# ログイントークンを作成する,mutationを定義
LOGIN_QUERY = self::Client.parse <<~GRAPHQL
mutation($input: ObtainJSONWebTokenInput!) {
obtainKrakenToken(input: $input) {
token
refreshToken
}
}
GRAPHQL
def generate_token
# mutationを実行してその実行結果をresultに格納する
result = Client.query(LOGIN_QUERY, variables: {
input: {
email: ENV["OCTOPUS_EMAIL"],
password: ENV["OCTOPUS_PASSWORD"],
},
})
result.original_hash.dig("data", "obtainKrakenToken", "token")
end
end
我們在上面進行了以下操作:設置了GraphQL用戶端的配置和查詢定義,並定義了用於創建令牌的方法。
使用认证令牌来获取电费信息。
好吧,现在我认为已经创建了认证令牌,所以我将根据该令牌创建用于获取电费的HTTP客户端。
require "graphql/client"
require "graphql/client/http"
module OctopusClient
HTTP = GraphQL::Client::HTTP.new("https://api.oejp-kraken.energy/v1/graphql/") do
def headers(context)
{ "Authorization" => "#{OctopusAuthenticationToken.new.generate_token}" }
end
end
Schema = GraphQL::Client.load_schema(HTTP)
Client = GraphQL::Client.new(schema: Schema, execute: HTTP)
end
在上述中,通过阅读lib/octopus_authentication_token.rb中创建的OctopusAuthenticationToken类的实例方法,获取令牌并设置到头部,在此基础上创建Client。
当你访问octopus_energy_bill/index时,会进行API调用的实现。
class OctopusEnergyBillController < ApplicationController
GetBillQUERY = OctopusClient::Client.parse <<~'GRAPHQL'
query(
$accountNumber: String!
$fromDatetime: DateTime
$toDatetime: DateTime
) {
account(accountNumber: $accountNumber) {
properties {
electricitySupplyPoints {
agreements {
validFrom
}
halfHourlyReadings(
fromDatetime: $fromDatetime
toDatetime: $toDatetime
) {
startAt
endAt
value
costEstimate
consumptionStep
consumptionRateBand
}
}
}
}
}
GRAPHQL
def index
result = OctopusClient::Client.query(GetBillQUERY, variables: {
accountNumber: ENV['OCTOPUS_ACCOUNT_NUMBER'],
fromDatetime: Date.yesterday.beginning_of_day.iso8601,
toDatetime: Date.yesterday.end_of_day.iso8601
})
properties = result.original_hash.dig("data", "account", "properties")
electricity_supply_points = properties.first["electricitySupplyPoints"]
half_hourly_readings = electricity_supply_points.first["halfHourlyReadings"]
@kwh = half_hourly_readings.pluck("value").map(&:to_f).sum
@cost = half_hourly_readings.pluck("costEstimate").map(&:to_f).sum
puts "#{Date.yesterday.strftime('%Y年%m月%d日')}は#{@kwh.round(2)}kWh消費して#{@cost}円かかったよ"
end
end
+ resources :octopus_energy_bill, only: %i[index]
另外,针对本次实施,我创建了一个问题(issue)来进行实施,如果有需要,可以作为参考。
利用 Line Messaging API 实现将获取的电费信息发送给用户的功能实例化。
我将像上一章一样安装下面的gem。
gem 'line-bot-api'
我們將創建一個Messaging API通道。
由於上述文章已經詳細解釋過,所以在本文中將省略不再提及。

在上述的形式下,我们制作了一个关于Octopus Energy的非官方机器人。
另外,将创建的渠道密钥命名为LINE_CHANNEL_SECRET,将渠道访问令牌命名为LINE_CHANNEL_TOKEN,并在.env文件中进行定义。
现在,我们将使用频道密钥和频道访问令牌来创建客户端。
class LineBotClient
def client
Line::Bot::Client.new { |config|
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
end
end
通过这个描述,您可以创建LineBotClient.new.client和Line::Bot::Client的实例。
好吧,让我们使用上面的内容来发送一条LINE消息吧!
class OctopusEnergyBillController < ApplicationController
GetBillQUERY = OctopusClient::Client.parse <<~'GRAPHQL'
query(
$accountNumber: String!
$fromDatetime: DateTime
$toDatetime: DateTime
) {
account(accountNumber: $accountNumber) {
properties {
electricitySupplyPoints {
agreements {
validFrom
}
halfHourlyReadings(
fromDatetime: $fromDatetime
toDatetime: $toDatetime
) {
startAt
endAt
value
costEstimate
consumptionStep
consumptionRateBand
}
}
}
}
}
GRAPHQL
def index
result = OctopusClient::Client.query(GetBillQUERY, variables: {
accountNumber: ENV['OCTOPUS_ACCOUNT_NUMBER'],
fromDatetime: Date.yesterday.beginning_of_day.iso8601,
toDatetime: Date.yesterday.end_of_day.iso8601
})
properties = result.original_hash.dig("data", "account", "properties")
electricity_supply_points = properties.first["electricitySupplyPoints"]
half_hourly_readings = electricity_supply_points.first["halfHourlyReadings"]
@kwh = half_hourly_readings.pluck("value").map(&:to_f).sum
@cost = half_hourly_readings.pluck("costEstimate").map(&:to_f).sum
- puts "#{Date.yesterday.strftime('%Y年%m月%d日')}は#{@kwh.round(2)}kWh消費して#{@cost}円かかったよ"
+ text = "#{Date.yesterday.strftime('%Y年%m月%d日')}は#{@kwh.round(2)}kWh消費して#{@cost}円かかったよ"
+ message = {
+ type: 'text',
+ text: text
+ }
+ LineBotClient.new.client.broadcast(message)
end
end
当您访问/octopus_energy_bill端点后,您可以通过LINE发送以下内容。

本次目标已经完成了!
最终
这次我们使用GraphQL和Rails(API模式)开发了一个电费Line机器人,您觉得如何?
下次我们打算进行部署和定期执行?
非常感谢您阅读至最后!
后续报道
文献引用