Skip to content

Commit 17d42af

Browse files
author
Lewis Youl
committed
feat: upload code snippet image to twitter
1 parent 6b8edea commit 17d42af

File tree

7 files changed

+133
-19
lines changed

7 files changed

+133
-19
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ gem "aws-sdk-s3", require: false
2929
gem 'redis'
3030
gem 'omniauth-github'
3131
gem 'omniauth-rails_csrf_protection'
32+
gem 'twitter'
3233

3334
# Use Redis adapter to run Action Cable in production
3435
# gem 'redis', '~> 4.0'

Gemfile.lock

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,40 @@ GEM
9595
bindex (0.8.1)
9696
bootsnap (1.4.6)
9797
msgpack (~> 1.0)
98+
buftok (0.2.0)
9899
builder (3.2.4)
99100
byebug (11.1.1)
100101
case_transform (0.2)
101102
activesupport
102103
concurrent-ruby (1.1.6)
103104
crass (1.0.6)
105+
domain_name (0.5.20190701)
106+
unf (>= 0.0.5, < 1.0.0)
107+
equalizer (0.0.11)
104108
erubi (1.9.0)
105109
faraday (1.3.0)
106110
faraday-net_http (~> 1.0)
107111
multipart-post (>= 1.2, < 3)
108112
ruby2_keywords
109113
faraday-net_http (1.0.1)
110114
ffi (1.12.2)
115+
ffi-compiler (1.0.1)
116+
ffi (>= 1.0.0)
117+
rake
111118
globalid (0.4.2)
112119
activesupport (>= 4.2.0)
113120
hashie (4.1.0)
121+
http (4.4.1)
122+
addressable (~> 2.3)
123+
http-cookie (~> 1.0)
124+
http-form_data (~> 2.2)
125+
http-parser (~> 1.2.0)
126+
http-cookie (1.0.3)
127+
domain_name (~> 0.5)
128+
http-form_data (2.3.0)
129+
http-parser (1.2.3)
130+
ffi-compiler (>= 1.0, < 2.0)
131+
http_parser.rb (0.6.0)
114132
i18n (1.8.2)
115133
concurrent-ruby (~> 1.0)
116134
jbuilder (2.10.0)
@@ -133,6 +151,8 @@ GEM
133151
mini_mime (>= 0.1.1)
134152
marcel (0.3.3)
135153
mimemagic (~> 0.3.2)
154+
memoizable (0.4.2)
155+
thread_safe (~> 0.3, >= 0.3.1)
136156
method_source (1.0.0)
137157
mimemagic (0.3.4)
138158
mini_mime (1.0.2)
@@ -142,6 +162,7 @@ GEM
142162
multi_json (1.15.0)
143163
multi_xml (0.6.0)
144164
multipart-post (2.1.1)
165+
naught (1.1.0)
145166
nio4r (2.5.2)
146167
nokogiri (1.10.9)
147168
mini_portile2 (~> 2.4.0)
@@ -223,6 +244,7 @@ GEM
223244
sprockets (> 3.0)
224245
sprockets-rails
225246
tilt
247+
simple_oauth (0.3.1)
226248
spring (2.1.0)
227249
spring-watcher-listen (2.0.1)
228250
listen (>= 2.7, < 4.0)
@@ -242,8 +264,22 @@ GEM
242264
turbolinks (5.2.1)
243265
turbolinks-source (~> 5.2)
244266
turbolinks-source (5.2.0)
267+
twitter (7.0.0)
268+
addressable (~> 2.3)
269+
buftok (~> 0.2.0)
270+
equalizer (~> 0.0.11)
271+
http (~> 4.0)
272+
http-form_data (~> 2.0)
273+
http_parser.rb (~> 0.6.0)
274+
memoizable (~> 0.4.0)
275+
multipart-post (~> 2.0)
276+
naught (~> 1.0)
277+
simple_oauth (~> 0.3.0)
245278
tzinfo (1.2.7)
246279
thread_safe (~> 0.1)
280+
unf (0.1.4)
281+
unf_ext
282+
unf_ext (0.0.7.7)
247283
warden (1.2.9)
248284
rack (>= 2.0.9)
249285
web-console (4.0.1)
@@ -284,6 +320,7 @@ DEPENDENCIES
284320
spring-watcher-listen (~> 2.0.0)
285321
tailwindcss-rails (~> 0.3.1)
286322
turbolinks (~> 5)
323+
twitter
287324
tzinfo-data
288325
web-console (>= 3.3.0)
289326
webpacker (~> 4.0)

app/controllers/tweets_controller.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class TweetsController < ApplicationController
2+
def create
3+
twitter_client.tweet_media(params[:data].path)
4+
end
5+
6+
private
7+
8+
def twitter_client
9+
Clients::Twitter.new
10+
end
11+
end
Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,71 @@
11
import { Controller } from 'stimulus';
22
import domtoimage from 'dom-to-image';
3+
import axios from 'axios'
34

45
export default class extends Controller {
56
static targets = ['code']
67

7-
capture() {
8-
const scale = 2;
9-
const node = this.codeTarget
10-
const options = {
11-
height: node.offsetHeight * scale,
12-
width: node.offsetWidth * scale,
13-
style: {
14-
transform: "scale(" + scale + ")",
15-
transformOrigin: "top left",
16-
width: node.offsetWidth + "px",
17-
height: node.offsetHeight + "px"
18-
}
19-
}
8+
initialize() {
9+
const csrfToken = document.querySelector("meta[name=csrf-token]").content
10+
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken
11+
}
2012

21-
domtoimage.toJpeg(node, options)
22-
.then(this.downloadImage)
23-
.catch(console.error)
13+
toDataUrl() {
14+
return domtoimage.toPng(this.codeTarget, this.imageConfig)
2415
}
2516

17+
toBlob() {
18+
return domtoimage.toBlob(this.codeTarget, this.imageConfig)
19+
}
20+
21+
tweet() {
22+
this.toBlob()
23+
.then(this.tweetImage)
24+
.catch(console.error)
25+
}
26+
27+
download() {
28+
this.toDataUrl()
29+
.then(this.downloadImage)
30+
.catch(console.error)
31+
}
32+
33+
tweetImage(blob) {
34+
let fd = new FormData();
35+
fd.append('fname', 'tweet.png');
36+
fd.append('data', blob);
37+
38+
const headers = { 'Content-Type': `multipart/form-data` }
39+
40+
axios.post(`/tweets`, fd, { headers })
41+
.then(res => {
42+
console.log('tweeted!')
43+
// create the twet intent with the created media url in it
44+
})
45+
.catch(console.error)
46+
}
47+
2648
downloadImage(dataUrl) {
2749
let link = document.createElement('a')
2850

29-
link.setAttribute('download', 'snippetsafe.jpeg');
51+
link.setAttribute('download', 'snippetsafe.png');
3052
link.setAttribute('href', dataUrl);
3153
link.click();
3254
link.remove()
3355
}
56+
57+
get imageConfig() {
58+
const scale = 2;
59+
60+
return {
61+
height: this.codeTarget.offsetHeight * scale,
62+
width: this.codeTarget.offsetWidth * scale,
63+
style: {
64+
transform: "scale(" + scale + ")",
65+
transformOrigin: "top left",
66+
width: this.codeTarget.offsetWidth + "px",
67+
height: this.codeTarget.offsetHeight + "px"
68+
}
69+
}
70+
}
3471
}

app/services/clients/twitter.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require 'twitter'
2+
3+
module Clients
4+
class Twitter
5+
6+
def tweet(body)
7+
client.update(body)
8+
end
9+
10+
def tweet_media(filepath)
11+
client.update_with_media('', File.new(filepath))
12+
end
13+
14+
private
15+
16+
def client
17+
@client ||= ::Twitter::REST::Client.new do |config|
18+
config.consumer_key = "0bEb97Ev9jfb0SdZAc3bnvuzq"
19+
config.consumer_secret = "x5cpKgPzcdhXXHPKDKOuo5JAIOhMDr3Y22SZiYwHrHvV9dUzuW"
20+
config.access_token = "1354061940260294656-OA3CosQ2hUd90llhxLubtdNASYfgaW"
21+
config.access_token_secret = "k8MZ8tCtvIJQs56FNjRzkbDHzY7BIkoOh5IVqAK4fnt4A"
22+
end
23+
end
24+
25+
end
26+
end

app/views/modals/snippets/picture.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</div>
88

99
<div class="flex justify-end mt-4">
10-
<%= button_tag('Tweet', class: 'button--disabled mr-2') %>
11-
<%= button_tag('Download', class: 'button--cta-tertiary', data: { action: 'click->picture#capture' }) %>
10+
<%= button_tag('Tweet', class: 'button--cta-tertiary mr-2', data: { action: 'click->picture#tweet' }) %>
11+
<%= button_tag('Download', class: 'button--cta-tertiary', data: { action: 'click->picture#download' }) %>
1212
</div>
1313
</div>

config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,6 @@
9797
put :file_snippet, on: :collection
9898
put :unfile_snippet, on: :collection
9999
end
100+
101+
resources :tweets, only: :create
100102
end

0 commit comments

Comments
 (0)