From 51f0030821f443a39d7eaa85eae6f191fef220b9 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Mon, 11 Nov 2019 09:39:21 -0500 Subject: [PATCH] Way late initial commit with GitHub posting working --- Gemfile | 9 ++++ Gemfile.lock | 63 ++++++++++++++++++++++ bin/bundle | 105 ++++++++++++++++++++++++++++++++++++ bin/dotenv | 29 ++++++++++ bin/puma | 29 ++++++++++ bin/pumactl | 29 ++++++++++ bin/rackup | 29 ++++++++++ bin/tilt | 29 ++++++++++ config.ru | 13 +++++ lib/micropub.rb | 7 +++ lib/micropub/github.rb | 41 ++++++++++++++ lib/micropub/models/post.rb | 52 ++++++++++++++++++ lib/micropub/webserver.rb | 35 ++++++++++++ micropub.rb | 20 +++++++ 14 files changed, 490 insertions(+) create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100755 bin/bundle create mode 100755 bin/dotenv create mode 100755 bin/puma create mode 100755 bin/pumactl create mode 100755 bin/rackup create mode 100755 bin/tilt create mode 100644 config.ru create mode 100644 lib/micropub.rb create mode 100644 lib/micropub/github.rb create mode 100644 lib/micropub/models/post.rb create mode 100644 lib/micropub/webserver.rb create mode 100644 micropub.rb diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..d6dcf9e --- /dev/null +++ b/Gemfile @@ -0,0 +1,9 @@ +source "https://rubygems.org" + +gem 'dotenv' + +gem "sinatra" +gem "sinatra-contrib" +gem "puma" + +gem "github_api" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..b8b9b4d --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,63 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + backports (3.15.0) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) + dotenv (2.7.5) + faraday (0.17.0) + multipart-post (>= 1.2, < 3) + github_api (0.18.2) + addressable (~> 2.4) + descendants_tracker (~> 0.0.4) + faraday (~> 0.8) + hashie (~> 3.5, >= 3.5.2) + oauth2 (~> 1.0) + hashie (3.6.0) + jwt (2.2.1) + multi_json (1.14.1) + multi_xml (0.6.0) + multipart-post (2.1.1) + mustermann (1.0.3) + nio4r (2.5.2) + oauth2 (1.4.2) + faraday (>= 0.8, < 2.0) + jwt (>= 1.0, < 3.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + public_suffix (4.0.1) + puma (4.2.1) + nio4r (~> 2.0) + rack (2.0.7) + rack-protection (2.0.7) + rack + sinatra (2.0.7) + mustermann (~> 1.0) + rack (~> 2.0) + rack-protection (= 2.0.7) + tilt (~> 2.0) + sinatra-contrib (2.0.7) + backports (>= 2.8.2) + multi_json + mustermann (~> 1.0) + rack-protection (= 2.0.7) + sinatra (= 2.0.7) + tilt (~> 2.0) + thread_safe (0.3.6) + tilt (2.0.10) + +PLATFORMS + ruby + +DEPENDENCIES + dotenv + github_api + puma + sinatra + sinatra-contrib + +BUNDLED WITH + 2.0.2 diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000..4f5e057 --- /dev/null +++ b/bin/bundle @@ -0,0 +1,105 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundle' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "rubygems" + +m = Module.new do + module_function + + def invoked_as_script? + File.expand_path($0) == File.expand_path(__FILE__) + end + + def env_var_version + ENV["BUNDLER_VERSION"] + end + + def cli_arg_version + return unless invoked_as_script? # don't want to hijack other binstubs + return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + bundler_version = nil + update_index = nil + ARGV.each_with_index do |a, i| + if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN + bundler_version = a + end + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ + bundler_version = $1 || ">= 0.a" + update_index = i + end + bundler_version + end + + def gemfile + gemfile = ENV["BUNDLE_GEMFILE"] + return gemfile if gemfile && !gemfile.empty? + + File.expand_path("../../Gemfile", __FILE__) + end + + def lockfile + lockfile = + case File.basename(gemfile) + when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) + else "#{gemfile}.lock" + end + File.expand_path(lockfile) + end + + def lockfile_version + return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ + Regexp.last_match(1) + end + + def bundler_version + @bundler_version ||= begin + env_var_version || cli_arg_version || + lockfile_version || "#{Gem::Requirement.default}.a" + end + end + + def load_bundler! + ENV["BUNDLE_GEMFILE"] ||= gemfile + + # must dup string for RG < 1.8 compatibility + activate_bundler(bundler_version.dup) + end + + def activate_bundler(bundler_version) + if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0") + bundler_version = "< 2" + end + gem_error = activation_error_handling do + gem "bundler", bundler_version + end + return if gem_error.nil? + require_error = activation_error_handling do + require "bundler/version" + end + return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`" + exit 42 + end + + def activation_error_handling + yield + nil + rescue StandardError, LoadError => e + e + end +end + +m.load_bundler! + +if m.invoked_as_script? + load Gem.bin_path("bundler", "bundle") +end diff --git a/bin/dotenv b/bin/dotenv new file mode 100755 index 0000000..a8ec8c7 --- /dev/null +++ b/bin/dotenv @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'dotenv' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("dotenv", "dotenv") diff --git a/bin/puma b/bin/puma new file mode 100755 index 0000000..880935b --- /dev/null +++ b/bin/puma @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'puma' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("puma", "puma") diff --git a/bin/pumactl b/bin/pumactl new file mode 100755 index 0000000..b698e6e --- /dev/null +++ b/bin/pumactl @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'pumactl' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("puma", "pumactl") diff --git a/bin/rackup b/bin/rackup new file mode 100755 index 0000000..3ac4a5a --- /dev/null +++ b/bin/rackup @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rackup' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rack", "rackup") diff --git a/bin/tilt b/bin/tilt new file mode 100755 index 0000000..34f7bca --- /dev/null +++ b/bin/tilt @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'tilt' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("tilt", "tilt") diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..6eaf072 --- /dev/null +++ b/config.ru @@ -0,0 +1,13 @@ +ENV['RACK_ENV'] ||= 'development' + +require 'dotenv' +Dotenv.load + +require 'bundler' + +Bundler.setup +Bundler.require(:default, ENV['RACK_ENV']) + +require File.expand_path('lib/micropub', __dir__) + +run Micropub::Webserver diff --git a/lib/micropub.rb b/lib/micropub.rb new file mode 100644 index 0000000..2b723c0 --- /dev/null +++ b/lib/micropub.rb @@ -0,0 +1,7 @@ +require 'json' + +module Micropub + autoload :Webserver, File.expand_path('micropub/webserver.rb', __dir__) + autoload :Github, File.expand_path('micropub/github.rb', __dir__) + autoload :Post, File.expand_path('micropub/models/post.rb', __dir__) +end diff --git a/lib/micropub/github.rb b/lib/micropub/github.rb new file mode 100644 index 0000000..786588e --- /dev/null +++ b/lib/micropub/github.rb @@ -0,0 +1,41 @@ +require "github_api" + +module Micropub + class Github + API_TOKEN = ENV["GITHUB_API_TOKEN"] + USER = ENV["GITHUB_USER"] + REPO = ENV["GITHUB_REPO"] + + CONTENT_PATH = "/content/blog" + + def initialize + @github = ::Github.new(oauth_token: API_TOKEN) + end + + def post!(post) + path = "content/blog/"\ + "#{post.published.strftime("%Y-%m-%d")}-#{post.id}/"\ + "index.md" + + github.repos.contents.create( + "danbee", + "danbarber.me.hugo", + path, + path: path, + message: "Posting a post", + content: post.post_content, + branch: "api_test", + ) + end + + def posts + @_posts ||= + github.repos.contents.get(USER, REPO, CONTENT_PATH). + map(&:name) + end + + private + + attr_accessor :github + end +end diff --git a/lib/micropub/models/post.rb b/lib/micropub/models/post.rb new file mode 100644 index 0000000..870aa0d --- /dev/null +++ b/lib/micropub/models/post.rb @@ -0,0 +1,52 @@ +class Post + attr_accessor :params + + def initialize(params) + @params = params + end + + def id + title. + downcase. + gsub(/[^a-z]+/, " "). + strip. + gsub(" ", "-") + end + + def title + params["title"] || truncated_content + end + + def truncated_content + content[0..content.index(".")]. + split(" "). + take(6). + join(" "). + gsub(/([a-z])$/, "\1…") + end + + def published + @_published ||= Date.parse(params["published"]) + end + + def categories + params["category"] + end + + def content + params["content"] + end + + def post_content + <<~POST + --- + date: '#{published.rfc3339}' + layout: micropost + categories: + #{categories.map { |category| "- #{category}\n" }.join.strip} + --- + + #{content} + POST + end +end diff --git a/lib/micropub/webserver.rb b/lib/micropub/webserver.rb new file mode 100644 index 0000000..266584d --- /dev/null +++ b/lib/micropub/webserver.rb @@ -0,0 +1,35 @@ +require 'sinatra' +require 'sinatra/contrib' + +module Micropub + class Webserver < Sinatra::Base + register Sinatra::ConfigFile + register Sinatra::Namespace + + set server: 'puma' + + github = Github.new + + get '/' do + "Hello, World!" + end + + get "/micropub" do + json data: { + posts: github.posts + } + end + + post "/micropub" do + # verify_token + + post = Post.new(params) + + if github.post!(post) + status 201 + else + status 400 + end + end + end +end diff --git a/micropub.rb b/micropub.rb new file mode 100644 index 0000000..6876eff --- /dev/null +++ b/micropub.rb @@ -0,0 +1,20 @@ +require "sinatra" +require "sinatra/json" + +require "./lib/post" + +post "/micropub" do + verify_token + + post = Post.new(params) + + if post.save! + status 201 + else + status 400 + end +end + +def verify_token + # verify token +end