Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Lyse
tt
Commits
05abee74
Commit
05abee74
authored
Jan 04, 2021
by
Lysander Trischler
Browse files
Add twt publish form
parent
42286c43
Changes
4
Hide whitespace changes
Inline
Side-by-side
README.rst
View file @
05abee74
...
...
@@ -13,8 +13,8 @@ At the moment it is a horribly hacked together piece of software that relies on
`my patched version <https://github.com/der-lyse/twtxt-1>`_ of the `twtxt CLI
client or reference implementation <https://github.com/buckket/twtxt/>`_ by the
original inventor of twtxt. ``tt`` only serves as a viewer of the twtxt
conversations, a `twtxt.net <https://twtxt.net/>`_ extension. It is
not
possible to post twts
with it yet
. The heavy lifting is still done by the
conversations, a `twtxt.net <https://twtxt.net/>`_ extension. It is
also
possible to post twts
or replies
. The heavy lifting is still done by the
reference implementation, especially fetching and storing the *twtxt.txt* files
in a local cache. ``tt`` just uses ``twtxt``'s *~/.config/twtxt/cache.db* for
all the twts to show. In a second cache file next to it – highly creatively
...
...
@@ -66,6 +66,7 @@ Features
* Open and copy links in URL view.
* Folding of mentions and twtxt subject hashes.
* Subject hashes can be hidden.
* Compose new or reply twts.
TODO
====
...
...
@@ -86,7 +87,6 @@ TODO
* Ability to show the txt's raw text.
* Manage subscriptions.
* Reload feeds.
* Compose twts.
WTF!
====
...
...
tt
View file @
05abee74
#!/usr/bin/python3
# encoding: utf-8
import
datetime
import
dateutil.parser
import
subprocess
import
twtxtmanager
import
twtxtparser
...
...
@@ -185,15 +187,27 @@ class TwtsListBox(widgets.VimListBox):
if
key
==
"q"
and
self
.
_search
:
self
.
clear_search
()
return
if
key
==
"t"
:
self
.
open_new_twt_form
()
return
if
key
==
"a"
:
self
.
open_reply_twt_form
()
return
return
super
().
keypress
(
size
,
key
)
def
toggle_read
(
self
):
@
property
def
selected_twt
(
self
):
pos
=
self
.
focus_position
twt
=
self
.
_twts
[
pos
]
return
self
.
_twts
[
pos
]
def
toggle_read
(
self
):
twt
=
self
.
selected_twt
self
.
_manager
.
toggle_read
(
twt
)
pos
=
self
.
focus_position
row
=
self
.
body
[
pos
]
row
.
set_attr_map
(
twtxtrenderer
.
read_normal_map
if
twt
.
read
else
twtxtrenderer
.
unread_normal_map
)
row
.
set_focus_map
(
twtxtrenderer
.
read_focus_map
if
twt
.
read
else
twtxtrenderer
.
unread_focus_map
)
...
...
@@ -201,8 +215,7 @@ class TwtsListBox(widgets.VimListBox):
def
list_urls
(
self
):
twt
=
self
.
_twts
[
self
.
focus_position
]
frame
.
body
.
push_widget
(
URLListBox
(
self
.
_manager
,
twt
))
frame
.
body
.
push_widget
(
URLListBox
(
self
.
_manager
,
self
.
selected_twt
))
def
_loop_twts
(
self
,
downwards
=
True
):
...
...
@@ -264,6 +277,14 @@ class TwtsListBox(widgets.VimListBox):
self
.
_search
=
None
def
open_new_twt_form
(
self
):
frame
.
body
.
push_widget
(
TwtForm
(
self
.
_manager
))
def
open_reply_twt_form
(
self
):
frame
.
body
.
push_widget
(
TwtForm
(
self
.
_manager
,
self
.
selected_twt
,
[
self
.
body
[
self
.
focus_position
]]))
class
URLListBox
(
widgets
.
VimListBox
):
CONV_URL
=
"https://twtxt.net/conv/%s"
...
...
@@ -401,6 +422,55 @@ class URLListBox(widgets.VimListBox):
subprocess
.
run
([
"twtxt"
,
"follow"
,
token
.
nick
,
token
.
url
])
class
TwtForm
(
urwid
.
ListBox
):
def
__init__
(
self
,
manager
,
original_twt
=
None
,
rendered_conversation
=
[]):
if
original_twt
:
authors
=
""
.
join
([
"@<%s %s> "
%
(
a
.
nick
,
a
.
url
)
for
a
in
self
.
_collect_authors
(
original_twt
)])
subject
=
"(#<%s %s>) "
%
(
original_twt
.
hash
,
"https://twtxt.net/conv/%s"
%
original_twt
.
hash
)
text
=
authors
+
subject
else
:
text
=
""
self
.
_text_edit
=
widgets
.
TextEdit
(
edit_text
=
text
)
self
.
_created_at_edit
=
widgets
.
TextEdit
(
edit_text
=
datetime
.
datetime
.
now
(
datetime
.
timezone
.
utc
)
.
replace
(
second
=
0
,
microsecond
=
0
)
.
astimezone
()
.
isoformat
())
publish
=
urwid
.
Button
(
"Publish Twt"
,
on_press
=
self
.
publish_twt
)
cancel
=
urwid
.
Button
(
"Cancel"
,
on_press
=
lambda
*
_
:
frame
.
body
.
pop_widget
())
super
().
__init__
(
list
(
map
(
widgets
.
Unselectable
,
rendered_conversation
))
+
[
urwid
.
LineBox
(
self
.
_text_edit
,
title
=
"Reply"
if
original_twt
else
"New Twt"
,
title_align
=
"left"
),
urwid
.
LineBox
(
self
.
_created_at_edit
,
title
=
"Created at"
,
title_align
=
"left"
),
urwid
.
Columns
([
urwid
.
Text
(
""
),
(
len
(
publish
.
label
)
+
4
,
publish
),
(
len
(
cancel
.
label
)
+
4
,
cancel
)],
dividechars
=
2
)])
self
.
_manager
=
manager
def
_collect_authors
(
self
,
twt
):
authors
=
[
twt
.
source
]
for
reply
in
twt
.
replies
:
for
reply_author
in
self
.
_collect_authors
(
reply
):
if
reply_author
not
in
authors
:
authors
.
append
(
reply_author
)
return
authors
def
publish_twt
(
self
,
*
_
):
created_at
=
dateutil
.
parser
.
parse
(
self
.
_created_at_edit
.
edit_text
)
if
not
created_at
.
tzinfo
:
created_at
=
created_at
.
replace
(
tzinfo
=
datetime
.
timezone
.
utc
)
text
=
self
.
_text_edit
.
edit_text
self
.
_manager
.
publish_twt
(
created_at
,
text
)
frame
.
body
.
pop_widget
()
show_subjects
=
False
fold_subjects
=
True
fold_mentions
=
True
...
...
twtxtmanager.py
View file @
05abee74
...
...
@@ -11,6 +11,7 @@ import twtxtparser
class
TwtxtManager
:
TWTXT_TXT
=
'/home/lyse/.config/twtxt/twtxt.txt'
def
__init__
(
self
):
self
.
_cache
=
None
...
...
@@ -37,10 +38,10 @@ class TwtxtManager:
self
.
read_twts_count
=
0
self
.
unread_twts_count
=
0
MAX_TWEETS_LIMIT
=
5
00
MAX_TWEETS_LIMIT
=
20
00
self
.
_cache
=
shelve
.
open
(
'/home/lyse/.config/twtxt/cache'
)
own_source
=
twtxt
.
models
.
Source
(
nick
=
"lyse"
,
url
=
"https://lyse.isobeef.org/twtxt.txt"
)
with
open
(
'/home/lyse/.config/twtxt/twtxt.txt'
,
'r'
,
encoding
=
'utf-8'
)
as
fd
:
with
open
(
self
.
TWTXT_TXT
,
'r'
,
encoding
=
'utf-8'
)
as
fd
:
own_twts
=
twtxt
.
parser
.
parse_tweets
(
fd
.
readlines
(),
own_source
)
self
.
_cache
[
own_source
.
url
]
=
{
'tweets'
:
own_twts
}
self
.
_cache2
=
shelve
.
open
(
'/home/lyse/.config/twtxt/cache2'
)
...
...
@@ -184,3 +185,13 @@ class TwtxtManager:
return
False
def
publish_twt
(
self
,
created_at
,
text
):
"""
Publish the given text at the specified timestamp by writing it to the
local twtxt.txt file.
"""
with
open
(
self
.
TWTXT_TXT
,
'a'
,
encoding
=
'utf-8'
)
as
fd
:
fd
.
write
(
"%s
\t
%s
\n
"
%
(
created_at
.
isoformat
(),
text
))
widgets.py
View file @
05abee74
...
...
@@ -27,6 +27,16 @@ class SelectableAttrMap(urwid.AttrMap):
return
key
class
Unselectable
(
urwid
.
WidgetWrap
):
"""
Just a wrapper around a selectable widget which should not be focusable
anymore.
"""
def
selectable
(
self
):
return
False
class
TextEdit
(
urwid
.
Edit
):
"""
More sophisticated urwid.Edit widget which has support for very common
...
...
@@ -44,17 +54,23 @@ class TextEdit(urwid.Edit):
key
=
"right"
elif
key
==
"ctrl left"
:
self
.
move_to_last_word
()
return
elif
key
==
"ctrl right"
:
self
.
move_to_next_word
()
return
elif
key
==
"ctrl w"
:
self
.
delete_last_word
()
return
elif
key
==
"ctrl k"
:
self
.
delete_to_end
()
return
elif
key
==
"meta d"
:
self
.
delete_next_word
()
return
elif
key
==
"ctrl u"
:
self
.
delete_to_home
()
super
().
keypress
(
size
,
key
)
return
return
super
().
keypress
(
size
,
key
)
def
_get_last_word_pos
(
self
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment