logicdn 1.0.469 → 1.0.473
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/logi.im/api/asset/data/bundle.json +1 -1
- package/logi.im/api/asset/data/friends-cached.json +68 -68
- package/logi.im/api/asset/data/nodes.info +1 -1
- package/logi.im/api/biz/friend.py +231 -228
- package/package.json +1 -1
- package/logi.im/api/asset/bin/np +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/OwO.custom.min.css +0 -1
- package/logi.im/usr/themes/Mirages/css/7.10.2/dashboard.settings.min.css +0 -1
- package/logi.im/usr/themes/Mirages/css/7.10.2/dashboard.write.min.css +0 -1
- package/logi.im/usr/themes/Mirages/css/7.10.2/fonts/fontawesome-webfont.eot +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/fonts/fontawesome-webfont.svg +0 -2671
- package/logi.im/usr/themes/Mirages/css/7.10.2/fonts/fontawesome-webfont.ttf +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/fonts/fontawesome-webfont.woff +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/fonts/fontawesome-webfont.woff2 +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/mirages.min.css +0 -1
- package/logi.im/usr/themes/Mirages/css/7.10.2/vditor/theme/light.css +0 -1
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-brands-400.eot +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-brands-400.svg +0 -3717
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-brands-400.ttf +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-brands-400.woff +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-brands-400.woff2 +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-regular-400.eot +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-regular-400.svg +0 -801
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-regular-400.ttf +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-regular-400.woff +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-regular-400.woff2 +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-solid-900.eot +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-solid-900.svg +0 -5028
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-solid-900.ttf +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-solid-900.woff +0 -0
- package/logi.im/usr/themes/Mirages/css/7.10.2/webfonts/fa-solid-900.woff2 +0 -0
- package/logi.im/usr/themes/Mirages/js/7.10.2/OwO.custom.min.js +0 -17
- package/logi.im/usr/themes/Mirages/js/7.10.2/OwO.json +0 -157
- package/logi.im/usr/themes/Mirages/js/7.10.2/dashboard.settings.min.js +0 -16
- package/logi.im/usr/themes/Mirages/js/7.10.2/mirages.main.min.js +0 -248
@@ -1,228 +1,231 @@
|
|
1
|
-
import os
|
2
|
-
import io
|
3
|
-
import sys
|
4
|
-
import time
|
5
|
-
import json
|
6
|
-
import shutil
|
7
|
-
import random
|
8
|
-
import subprocess
|
9
|
-
from datetime import datetime
|
10
|
-
from urllib.parse import urlsplit
|
11
|
-
from concurrent.futures import ThreadPoolExecutor
|
12
|
-
|
13
|
-
import requests
|
14
|
-
from PIL import Image
|
15
|
-
|
16
|
-
TIME_OUT = 20
|
17
|
-
MAX_TRY = 3
|
18
|
-
POOL_SIZE = 5
|
19
|
-
PROXY = 'http://127.0.0.1:8888'
|
20
|
-
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36'
|
21
|
-
WHITE_LIST = ['cnblogs.com']
|
22
|
-
TODAY = datetime.today().strftime('%Y-%m-%d')
|
23
|
-
|
24
|
-
CONF_PATH = 'asset/data/friends.json'
|
25
|
-
CONF_CACHED_PATH = 'asset/data/friends-cached.json'
|
26
|
-
IMG_PATH = 'asset/img'
|
27
|
-
NP_PATH = 'asset/
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
os.system(
|
35
|
-
|
36
|
-
os.system('
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
1
|
+
import os
|
2
|
+
import io
|
3
|
+
import sys
|
4
|
+
import time
|
5
|
+
import json
|
6
|
+
import shutil
|
7
|
+
import random
|
8
|
+
import subprocess
|
9
|
+
from datetime import datetime
|
10
|
+
from urllib.parse import urlsplit
|
11
|
+
from concurrent.futures import ThreadPoolExecutor
|
12
|
+
|
13
|
+
import requests
|
14
|
+
from PIL import Image
|
15
|
+
|
16
|
+
TIME_OUT = 20
|
17
|
+
MAX_TRY = 3
|
18
|
+
POOL_SIZE = 5
|
19
|
+
PROXY = 'http://127.0.0.1:8888'
|
20
|
+
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36'
|
21
|
+
WHITE_LIST = ['cnblogs.com']
|
22
|
+
TODAY = datetime.today().strftime('%Y-%m-%d')
|
23
|
+
|
24
|
+
CONF_PATH = 'asset/data/friends.json'
|
25
|
+
CONF_CACHED_PATH = 'asset/data/friends-cached.json'
|
26
|
+
IMG_PATH = 'asset/img'
|
27
|
+
NP_PATH = 'asset/data/np'
|
28
|
+
NP_URI = 'https://github.com/vcheckzen/normalize-http-proxy/raw/main/dist/np_linux_amd64'
|
29
|
+
|
30
|
+
|
31
|
+
class FriendLinkDoctor:
|
32
|
+
def __init__(self, init=False):
|
33
|
+
if sys.platform.startswith('linux'):
|
34
|
+
# os.system('ls -l')
|
35
|
+
os.system(f'curl -s -o {NP_PATH} -L {NP_URI}')
|
36
|
+
os.system(f'chmod +x {NP_PATH}')
|
37
|
+
self.proxy_process = subprocess.Popen([NP_PATH, "baidu"])
|
38
|
+
os.system('curl -s -o /dev/null -x ' +
|
39
|
+
PROXY + ' http://www.baidu.com')
|
40
|
+
|
41
|
+
self.init = init
|
42
|
+
conf = CONF_PATH if init else CONF_CACHED_PATH
|
43
|
+
|
44
|
+
with open(conf, mode='r', encoding='utf-8') as f:
|
45
|
+
self.friends = json.load(f)
|
46
|
+
|
47
|
+
def __del__(self):
|
48
|
+
if sys.platform.startswith('linux'):
|
49
|
+
self.proxy_process.terminate()
|
50
|
+
os.system(f'rm -f {NP_PATH}')
|
51
|
+
# self.proxy_process.kill()
|
52
|
+
|
53
|
+
@staticmethod
|
54
|
+
def get(url, **args):
|
55
|
+
return requests.get(
|
56
|
+
url,
|
57
|
+
timeout=TIME_OUT,
|
58
|
+
headers={'User-Agent': USER_AGENT,
|
59
|
+
'X-Forwarded-For': '2606:4700::6810:85e5, 112.88.0.1, 162.158.0.1'},
|
60
|
+
proxies={'http': PROXY, 'https': PROXY},
|
61
|
+
**args
|
62
|
+
)
|
63
|
+
|
64
|
+
"""
|
65
|
+
msg = str(e)
|
66
|
+
if msg.find('get local issuer certificate') > -1:
|
67
|
+
return True
|
68
|
+
elif msg.find('certificate has expired') > -1:
|
69
|
+
return fail()
|
70
|
+
elif msg.find('sslv3 alert handshake failure') > -1:
|
71
|
+
return fail()
|
72
|
+
elif msg.find('Connection reset by peer') > -1:
|
73
|
+
return fail()
|
74
|
+
elif msg.find('length mismatch') > -1:
|
75
|
+
return fail()
|
76
|
+
elif msg.find('doesn\'t match') > -1:
|
77
|
+
return fail()
|
78
|
+
elif msg.find('Temporary failure in name resolution') > -1:
|
79
|
+
return fail()
|
80
|
+
elif msg.find('No address associated with hostname') > -1:
|
81
|
+
return fail()
|
82
|
+
elif msg.find('Name or service not known') > -1:
|
83
|
+
return fail()
|
84
|
+
elif msg.find('getaddrinfo failed') > -1:
|
85
|
+
return fail()
|
86
|
+
print(e)
|
87
|
+
"""
|
88
|
+
@staticmethod
|
89
|
+
def try_your_best(fn, fail):
|
90
|
+
for _ in range(MAX_TRY):
|
91
|
+
try:
|
92
|
+
return fn()
|
93
|
+
except Exception as e:
|
94
|
+
msg = str(e)
|
95
|
+
if msg.find('get local issuer certificate') > -1:
|
96
|
+
return True
|
97
|
+
# print(msg)
|
98
|
+
time.sleep(random.randint(5, 7))
|
99
|
+
pass
|
100
|
+
|
101
|
+
return fail()
|
102
|
+
|
103
|
+
@staticmethod
|
104
|
+
def save_image(friend):
|
105
|
+
requests.packages.urllib3.disable_warnings()
|
106
|
+
link = friend['link']
|
107
|
+
identity = urlsplit(link).netloc
|
108
|
+
|
109
|
+
def save():
|
110
|
+
resp = FriendLinkDoctor.get(friend['avatar'], verify=False)
|
111
|
+
|
112
|
+
path = urlsplit(friend['avatar']).path
|
113
|
+
if path.find('.') > 0:
|
114
|
+
suffix = path.split('.')[-1]
|
115
|
+
else:
|
116
|
+
suffix = resp.headers.get('content-type').split('/')[-1]
|
117
|
+
if suffix == 'jpeg':
|
118
|
+
suffix = 'jpg'
|
119
|
+
|
120
|
+
name = f'{IMG_PATH}/{identity}.{suffix}'
|
121
|
+
img = Image.open(io.BytesIO(resp.content))
|
122
|
+
img.thumbnail((200, 200))
|
123
|
+
width, height = img.size # Get dimensions
|
124
|
+
|
125
|
+
if width != height:
|
126
|
+
new_width = min(width, height)
|
127
|
+
left = round((width - new_width)/2)
|
128
|
+
top = round((height - new_width)/2)
|
129
|
+
x_right = round(width - new_width) - left
|
130
|
+
x_bottom = round(height - new_width) - top
|
131
|
+
right = width - x_right
|
132
|
+
bottom = height - x_bottom
|
133
|
+
|
134
|
+
# Crop the center of the image
|
135
|
+
img = img.crop((left, top, right, bottom))
|
136
|
+
|
137
|
+
img.save(name)
|
138
|
+
friend['avatar'] = name
|
139
|
+
|
140
|
+
def fail():
|
141
|
+
for img in os.listdir(IMG_PATH):
|
142
|
+
if img.find(identity) > -1:
|
143
|
+
friend['avatar'] = f'{IMG_PATH}/{img}'
|
144
|
+
print(f'failure, using cached file: {link}')
|
145
|
+
return
|
146
|
+
print(f'failure: {link}')
|
147
|
+
|
148
|
+
FriendLinkDoctor.try_your_best(save, fail)
|
149
|
+
return friend
|
150
|
+
|
151
|
+
@staticmethod
|
152
|
+
def is_online(url):
|
153
|
+
url_404 = f'{url}/not-exists/be4b3658-2045-4468-8530-cc11c2145849'
|
154
|
+
error_text = 'www.beian.miit.gov.cn/state/outPortal/loginPortal.action'
|
155
|
+
|
156
|
+
def fail():
|
157
|
+
print(f'offline: {url}')
|
158
|
+
return False
|
159
|
+
|
160
|
+
def req():
|
161
|
+
if FriendLinkDoctor.get(url_404).text.find(error_text) == -1:
|
162
|
+
return True
|
163
|
+
return fail()
|
164
|
+
|
165
|
+
return FriendLinkDoctor.try_your_best(req, fail)
|
166
|
+
|
167
|
+
def save_config(self, results):
|
168
|
+
if self.init:
|
169
|
+
def retrieve_online_date(friend, old_result):
|
170
|
+
old_friend = list(
|
171
|
+
filter(lambda old_friend: old_friend['link'] == friend['link'], old_result))
|
172
|
+
if len(old_friend) == 1 and 'lastOnlineDate' in old_friend[0]:
|
173
|
+
friend['lastOnlineDate'] = old_friend[0]['lastOnlineDate']
|
174
|
+
return friend
|
175
|
+
|
176
|
+
with open(CONF_CACHED_PATH, mode='r', encoding='utf-8') as f:
|
177
|
+
old_result = json.load(f)
|
178
|
+
results = list(map(lambda friend: retrieve_online_date(
|
179
|
+
friend, old_result), results))
|
180
|
+
|
181
|
+
with open(CONF_CACHED_PATH, mode='w', encoding='utf-8') as f:
|
182
|
+
json.dump(
|
183
|
+
results,
|
184
|
+
f,
|
185
|
+
ensure_ascii=False,
|
186
|
+
sort_keys=True,
|
187
|
+
indent=2
|
188
|
+
)
|
189
|
+
|
190
|
+
def concurrent_task(self, fn):
|
191
|
+
futures, pool = [], ThreadPoolExecutor(POOL_SIZE)
|
192
|
+
for friend in self.friends:
|
193
|
+
futures.append(pool.submit(fn, friend))
|
194
|
+
|
195
|
+
results = []
|
196
|
+
for future in futures:
|
197
|
+
results.append(future.result())
|
198
|
+
|
199
|
+
self.save_config(results)
|
200
|
+
|
201
|
+
return results
|
202
|
+
|
203
|
+
def check_boby(self):
|
204
|
+
def check(friend):
|
205
|
+
for host in WHITE_LIST:
|
206
|
+
if friend['link'].find(host) > 0:
|
207
|
+
friend['lastOnlineDate'] = TODAY
|
208
|
+
friend['untracked'] = True
|
209
|
+
return friend
|
210
|
+
|
211
|
+
if self.is_online(friend['link']):
|
212
|
+
friend['lastOnlineDate'] = TODAY
|
213
|
+
return friend
|
214
|
+
|
215
|
+
return self.concurrent_task(check)
|
216
|
+
|
217
|
+
def get_images(self):
|
218
|
+
if os.path.exists(IMG_PATH):
|
219
|
+
shutil.copytree(IMG_PATH, IMG_PATH + '_copied')
|
220
|
+
# shutil.rmtree(IMG_PATH)
|
221
|
+
else:
|
222
|
+
os.mkdir(IMG_PATH)
|
223
|
+
|
224
|
+
self.concurrent_task(self.save_image)
|
225
|
+
|
226
|
+
|
227
|
+
if __name__ == '__main__':
|
228
|
+
if len(sys.argv) != 1 and sys.argv[1] == 'init':
|
229
|
+
FriendLinkDoctor(init=True).get_images()
|
230
|
+
else:
|
231
|
+
FriendLinkDoctor().check_boby()
|
package/package.json
CHANGED
package/logi.im/api/asset/bin/np
DELETED
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
/*! OwO.custom.css */.gradient-background{background:linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);background-size:1000% 1000%;-webkit-animation:Gradient 90s linear infinite;-moz-animation:Gradient 90s linear infinite;animation:Gradient 90s linear infinite}@-webkit-keyframes Gradient{0%{background-position:0 50%}50%{background-position:100% 50%}100%{background-position:0 50%}}@-moz-keyframes Gradient{0%{background-position:0 50%}50%{background-position:100% 50%}100%{background-position:0 50%}}@keyframes Gradient{0%{background-position:0 50%}50%{background-position:100% 50%}100%{background-position:0 50%}}.OwO{position:relative;user-select:none;margin-top:10px;display:block}.OwO#owo-vditor{position:absolute;margin-top:1px;margin-left:5px}body.vditor-mode-fullscreen .OwO#owo-vditor{left:0;top:0}.OwO:hover .OwO-logo{color:#ccc}.OwO.OwO-open .OwO-logo{border-radius:4px 4px 0 0;border-bottom:none;color:#ccc}.OwO.OwO-open .OwO-body{display:block}.OwO.OwO-up .OwO-body{top:inherit;bottom:21px;border-radius:4px 4px 4px 0}.OwO.OwO-up .OwO-body .OwO-bar .OwO-packages li:nth-child(1){border-radius:0}.OwO.OwO-up.OwO-open .OwO-logo{border:1px solid #ddd;border-radius:0 0 4px 4px;border-top:none}.OwO .OwO-logo{position:relative;display:inline-block;color:#999;border:2px solid #777;border-radius:4px;font-size:13px;padding:2px 5px;cursor:pointer;height:22px;box-sizing:border-box;z-index:2;line-height:16px}body.theme-white .OwO .OwO-logo{color:#777;border-color:#ececec}body.theme-dark .OwO .OwO-logo{border-color:#555}body.theme-dark.dark-mode .OwO .OwO-logo{border-color:#777}.OwO .OwO-logo:hover span{display:inline-block}.OwO#owo-vditor .OwO-logo{display:none}.OwO .OwO-body{display:none;position:absolute;width:400px;background:#2c2a2a;border:2px solid #777;z-index:9999;top:21px;border-radius:0 4px 4px 4px;white-space:normal;-webkit-overflow-scrolling:touch}body.theme-dark .OwO .OwO-body{border-color:#555}body.theme-dark.dark-mode .OwO .OwO-body{border-color:#777}.OwO .OwO-body .OwO-items{user-select:none;display:none;padding:10px;margin:0;overflow:auto;font-size:0}.OwO .OwO-body .OwO-items .OwO-item{list-style-type:none;background:rgba(255,255,255,0.04);padding:5px 10px;border-radius:5px;display:inline-block;font-size:12px;line-height:14px;margin:0 10px 12px 0;cursor:pointer;transition:.3s}.OwO .OwO-body .OwO-items .OwO-item:hover{background:rgba(255,255,255,0.12);transform:scale(1.2)}.OwO .OwO-body .OwO-items-emoji .OwO-item{font-size:20px;line-height:19px}.OwO .OwO-body .OwO-items-image .OwO-item{max-width:calc(25% - 10px);box-sizing:border-box}.OwO .OwO-body .OwO-items-image .OwO-item img{max-width:100%}.OwO .OwO-body .OwO-items-show{display:block}.OwO .OwO-body .OwO-bar{width:100%;height:30px;border-top:2px solid #555;background:#2c2a2a;border-radius:0 0 4px 4px;color:#ccc;overflow-y:hidden}.OwO .OwO-body .OwO-bar .OwO-packages{margin:0;padding:0;font-size:0}.OwO .OwO-body .OwO-bar .OwO-packages li{list-style-type:none;display:inline-block;line-height:30px;font-size:14px;padding:0 10px;cursor:pointer;margin-right:3px}.OwO .OwO-body .OwO-bar .OwO-packages li:nth-child(1){border-radius:0 0 0 3px}.OwO .OwO-body .OwO-bar .OwO-packages li:hover{background:rgba(255,255,255,0.12)}.OwO .OwO-body .OwO-bar .OwO-packages .OwO-package-active{background:rgba(255,255,255,0.12);transition:.3s}.OwO#owo-vditor .OwO-body{min-width:350px;top:35px}body.vditor-mode-fullscreen .OwO#owo-vditor .OwO-body{position:fixed}body.OwO-open #body{overflow-y:inherit;overflow-x:hidden}body.theme-white .OwO:hover .OwO-logo{color:#444}body.theme-white .OwO .OwO-body{background:#fff;border-color:#ececec}body.theme-white .OwO .OwO-body .OwO-items .OwO-item{background:#f7f7f7}body.theme-white .OwO .OwO-body .OwO-items .OwO-item:hover{background:#eee}body.theme-white .OwO .OwO-body .OwO-bar{border-top-color:#ececec;background:#fff;color:#444}body.theme-white .OwO .OwO-body .OwO-bar .OwO-packages li:hover{background:#eee}body.theme-white .OwO .OwO-body .OwO-bar .OwO-packages .OwO-package-active{background:#eee}body.theme-white.theme-sunset .OwO-logo{border-color:#d6d0c2}body.theme-white.theme-sunset .OwO-body{background:#FFF8EB;border-color:#d6d0c2}body.theme-white.theme-sunset .OwO-body .OwO-items .OwO-item{background:#F8F1E4}body.theme-white.theme-sunset .OwO-body .OwO-items .OwO-item:hover{background:#e7e0d3}body.theme-white.theme-sunset .OwO-body .OwO-bar{background:#FFF8EB;border-top-color:#d6d0c2}body.theme-white.theme-sunset .OwO-body .OwO-bar .OwO-packages li:hover{background:#F8F1E4}body.theme-white.theme-sunset .OwO-body .OwO-bar .OwO-packages .OwO-package-active{background:#F8F1E4}
|